From f62d417825d6a8e26768a130a5f4c9e454d9dbe4 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 15 May 2014 15:57:54 -0400 Subject: [PATCH] Fix unportable setvbuf() usage in initdb. In yesterday's commit 2dc4f011fd61501cce507be78c39a2677690d44b, I tried to force buffering of stdout/stderr in initdb to be what it is by default when the program is run interactively on Unix (since that's how most manual testing is done). This tripped over the fact that Windows doesn't support _IOLBF mode. We dealt with that a long time ago in syslogger.c by falling back to unbuffered mode on Windows. Export that solution in port.h and use it in initdb. Back-patch to 8.4, like the previous commit. --- src/backend/postmaster/syslogger.c | 17 +++-------------- src/bin/initdb/initdb.c | 2 +- src/include/port.h | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c index f89a5339e0..916519be50 100644 --- a/src/backend/postmaster/syslogger.c +++ b/src/backend/postmaster/syslogger.c @@ -47,17 +47,6 @@ #include "utils/ps_status.h" #include "utils/timestamp.h" -/* - * We really want line-buffered mode for logfile output, but Windows does - * not have it, and interprets _IOLBF as _IOFBF (bozos). So use _IONBF - * instead on Windows. - */ -#ifdef WIN32 -#define LBF_MODE _IONBF -#else -#define LBF_MODE _IOLBF -#endif - /* * We read() into a temp buffer twice as big as a chunk, so that any fragment * left after processing can be moved down to the front and we'll still have @@ -765,7 +754,7 @@ syslogger_parseArgs(int argc, char *argv[]) if (fd != -1) { syslogFile = fdopen(fd, "a"); - setvbuf(syslogFile, NULL, LBF_MODE, 0); + setvbuf(syslogFile, NULL, PG_IOLBF, 0); } #else /* WIN32 */ fd = atoi(*argv++); @@ -775,7 +764,7 @@ syslogger_parseArgs(int argc, char *argv[]) if (fd > 0) { syslogFile = fdopen(fd, "a"); - setvbuf(syslogFile, NULL, LBF_MODE, 0); + setvbuf(syslogFile, NULL, PG_IOLBF, 0); } } #endif /* WIN32 */ @@ -1154,7 +1143,7 @@ logfile_open(const char *filename, const char *mode, bool allow_errors) if (fh) { - setvbuf(fh, NULL, LBF_MODE, 0); + setvbuf(fh, NULL, PG_IOLBF, 0); #ifdef WIN32 /* use CRLF line endings on Windows */ diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index acaae02980..5228f13422 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -3529,7 +3529,7 @@ main(int argc, char *argv[]) * unexpected output ordering when, eg, output is redirected to a file. * POSIX says we must do this before any other usage of these files. */ - setvbuf(stdout, NULL, _IOLBF, 0); + setvbuf(stdout, NULL, PG_IOLBF, 0); setvbuf(stderr, NULL, _IONBF, 0); progname = get_progname(argv[0]); diff --git a/src/include/port.h b/src/include/port.h index 3d7f267554..c9226f3dac 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -338,6 +338,20 @@ extern int gettimeofday(struct timeval * tp, struct timezone * tzp); #define closesocket close #endif /* WIN32 */ +/* + * On Windows, setvbuf() does not support _IOLBF mode, and interprets that + * as _IOFBF. To add insult to injury, setvbuf(file, NULL, _IOFBF, 0) + * crashes outright if "parameter validation" is enabled. Therefore, in + * places where we'd like to select line-buffered mode, we fall back to + * unbuffered mode instead on Windows. Always use PG_IOLBF not _IOLBF + * directly in order to implement this behavior. + */ +#ifndef WIN32 +#define PG_IOLBF _IOLBF +#else +#define PG_IOLBF _IONBF +#endif + /* * Default "extern" declarations or macro substitutes for library routines. * When necessary, these routines are provided by files in src/port/.