@@ -37,19 +37,29 @@ static intwin32_check_directory_write_permissions(void);
3737 * If throw_error is true, this raises a PG_FATAL error and pg_upgrade
3838 * terminates; otherwise it is just reported as PG_REPORT and exec_prog()
3939 * returns false.
40+ *
41+ * The code requires it be called first from the primary thread on Windows.
4042 */
4143bool
4244exec_prog (const char * log_file ,const char * opt_log_file ,
4345bool throw_error ,const char * fmt ,...)
4446{
45- int result ;
47+ int result = 0 ;
4648int written ;
4749
4850#define MAXCMDLEN (2 * MAXPGPATH)
4951char cmd [MAXCMDLEN ];
5052FILE * log ;
5153va_list ap ;
5254
55+ #ifdef WIN32
56+ static DWORD mainThreadId = 0 ;
57+
58+ /* We assume we are called from the primary thread first */
59+ if (mainThreadId == 0 )
60+ mainThreadId = GetCurrentThreadId ();
61+ #endif
62+
5363written = strlcpy (cmd ,SYSTEMQUOTE ,sizeof (cmd ));
5464va_start (ap ,fmt );
5565written += vsnprintf (cmd + written ,MAXCMDLEN - written ,fmt ,ap );
@@ -61,6 +71,22 @@ exec_prog(const char *log_file, const char *opt_log_file,
6171if (written >=MAXCMDLEN )
6272pg_log (PG_FATAL ,"command too long\n" );
6373
74+ pg_log (PG_VERBOSE ,"%s\n" ,cmd );
75+
76+ #ifdef WIN32
77+ /*
78+ * For some reason, Windows issues a file-in-use error if we write data
79+ * to the log file from a non-primary thread just before we create a
80+ * subprocess that also writes to the same log file. One fix is to
81+ * sleep for 100ms. A cleaner fix is to write to the log file _after_
82+ * the subprocess has completed, so we do this only when writing from
83+ * a non-primary thread. fflush(), running system() twice, and
84+ * pre-creating the file do not see to help.
85+ */
86+ if (mainThreadId != GetCurrentThreadId ())
87+ result = system (cmd );
88+ #endif
89+
6490log = fopen (log_file ,"a" );
6591
6692#ifdef WIN32
@@ -84,19 +110,30 @@ exec_prog(const char *log_file, const char *opt_log_file,
84110
85111if (log == NULL )
86112pg_log (PG_FATAL ,"cannot write to log file %s\n" ,log_file );
113+
87114#ifdef WIN32
88- fprintf (log ,"\n\n" );
115+ /* Are we printing "command:" before its output? */
116+ if (mainThreadId == GetCurrentThreadId ())
117+ fprintf (log ,"\n\n" );
89118#endif
90- pg_log (PG_VERBOSE ,"%s\n" ,cmd );
91119fprintf (log ,"command: %s\n" ,cmd );
120+ #ifdef WIN32
121+ /* Are we printing "command:" after its output? */
122+ if (mainThreadId != GetCurrentThreadId ())
123+ fprintf (log ,"\n\n" );
124+ #endif
92125
93126/*
94127 * In Windows, we must close the log file at this point so the file is not
95128 * open while the command is running, or we get a share violation.
96129 */
97130fclose (log );
98131
99- result = system (cmd );
132+ #ifdef WIN32
133+ /* see comment above */
134+ if (mainThreadId == GetCurrentThreadId ())
135+ #endif
136+ result = system (cmd );
100137
101138if (result != 0 )
102139{
@@ -118,7 +155,6 @@ exec_prog(const char *log_file, const char *opt_log_file,
118155}
119156
120157#ifndef WIN32
121-
122158/*
123159 * We can't do this on Windows because it will keep the "pg_ctl start"
124160 * output filename open until the server stops, so we do the \n\n above on