1818 *
1919 *
2020 * IDENTIFICATION
21- * $PostgreSQL: pgsql/src/backend/postmaster/syslogger.c,v 1.56 2010/04/01 20:12:22 heikki Exp $
21+ * $PostgreSQL: pgsql/src/backend/postmaster/syslogger.c,v 1.57 2010/04/16 09:51:49 heikki Exp $
2222 *
2323 *-------------------------------------------------------------------------
2424 */
@@ -117,7 +117,7 @@ HANDLEsyslogPipe[2] = {0, 0};
117117
118118#ifdef WIN32
119119static HANDLE threadHandle = 0 ;
120- static CRITICAL_SECTION sysfileSection ;
120+ static CRITICAL_SECTION sysloggerSection ;
121121#endif
122122
123123/*
@@ -268,7 +268,8 @@ SysLoggerMain(int argc, char *argv[])
268268
269269#ifdef WIN32
270270/* Fire up separate data transfer thread */
271- InitializeCriticalSection (& sysfileSection );
271+ InitializeCriticalSection (& sysloggerSection );
272+ EnterCriticalSection (& sysloggerSection );
272273
273274threadHandle = (HANDLE )_beginthreadex (NULL ,0 ,pipeThread ,NULL ,0 ,NULL );
274275if (threadHandle == 0 )
@@ -423,8 +424,16 @@ SysLoggerMain(int argc, char *argv[])
423424 * On Windows we leave it to a separate thread to transfer data and
424425 * detect pipe EOF. The main thread just wakes up once a second to
425426 * check for SIGHUP and rotation conditions.
427+ *
428+ * Server code isn't generally thread-safe, so we ensure that only
429+ * one of the threads is active at a time by entering the critical
430+ * section whenever we're not sleeping.
426431 */
432+ LeaveCriticalSection (& sysloggerSection );
433+
427434pg_usleep (1000000L );
435+
436+ EnterCriticalSection (& sysloggerSection );
428437#endif /* WIN32 */
429438
430439if (pipe_eof_seen )
@@ -911,17 +920,9 @@ write_syslogger_file(const char *buffer, int count, int destination)
911920if (destination == LOG_DESTINATION_CSVLOG && csvlogFile == NULL )
912921open_csvlogfile ();
913922
914- #ifdef WIN32
915- EnterCriticalSection (& sysfileSection );
916- #endif
917-
918923logfile = destination == LOG_DESTINATION_CSVLOG ?csvlogFile :syslogFile ;
919924rc = fwrite (buffer ,1 ,count ,logfile );
920925
921- #ifdef WIN32
922- LeaveCriticalSection (& sysfileSection );
923- #endif
924-
925926/* can't use ereport here because of possible recursion */
926927if (rc != count )
927928write_stderr ("could not write to log file: %s\n" ,strerror (errno ));
@@ -945,11 +946,21 @@ pipeThread(void *arg)
945946for (;;)
946947{
947948DWORD bytesRead ;
949+ BOOL result ;
950+
951+ result = ReadFile (syslogPipe [0 ],
952+ logbuffer + bytes_in_logbuffer ,
953+ sizeof (logbuffer )- bytes_in_logbuffer ,
954+ & bytesRead ,0 );
948955
949- if (!ReadFile (syslogPipe [0 ],
950- logbuffer + bytes_in_logbuffer ,
951- sizeof (logbuffer )- bytes_in_logbuffer ,
952- & bytesRead ,0 ))
956+ /*
957+ * Enter critical section before doing anything that might touch
958+ * global state shared by the main thread. Anything that uses
959+ * palloc()/pfree() in particular are not safe outside the critical
960+ * section.
961+ */
962+ EnterCriticalSection (& sysloggerSection );
963+ if (!result )
953964{
954965DWORD error = GetLastError ();
955966
@@ -966,6 +977,7 @@ pipeThread(void *arg)
966977bytes_in_logbuffer += bytesRead ;
967978process_pipe_input (logbuffer ,& bytes_in_logbuffer );
968979}
980+ LeaveCriticalSection (& sysloggerSection );
969981}
970982
971983/* We exit the above loop only upon detecting pipe EOF */
@@ -974,6 +986,7 @@ pipeThread(void *arg)
974986/* if there's any data left then force it out now */
975987flush_pipe_input (logbuffer ,& bytes_in_logbuffer );
976988
989+ LeaveCriticalSection (& sysloggerSection );
977990_endthread ();
978991return 0 ;
979992}
@@ -1097,18 +1110,9 @@ logfile_rotate(bool time_based_rotation, int size_rotation_for)
10971110_setmode (_fileno (fh ),_O_TEXT );/* use CRLF line endings on Windows */
10981111#endif
10991112
1100- /* On Windows, need to interlock against data-transfer thread */
1101- #ifdef WIN32
1102- EnterCriticalSection (& sysfileSection );
1103- #endif
1104-
11051113fclose (syslogFile );
11061114syslogFile = fh ;
11071115
1108- #ifdef WIN32
1109- LeaveCriticalSection (& sysfileSection );
1110- #endif
1111-
11121116/* instead of pfree'ing filename, remember it for next time */
11131117if (last_file_name != NULL )
11141118pfree (last_file_name );
@@ -1164,18 +1168,9 @@ logfile_rotate(bool time_based_rotation, int size_rotation_for)
11641168_setmode (_fileno (fh ),_O_TEXT );/* use CRLF line endings on Windows */
11651169#endif
11661170
1167- /* On Windows, need to interlock against data-transfer thread */
1168- #ifdef WIN32
1169- EnterCriticalSection (& sysfileSection );
1170- #endif
1171-
11721171fclose (csvlogFile );
11731172csvlogFile = fh ;
11741173
1175- #ifdef WIN32
1176- LeaveCriticalSection (& sysfileSection );
1177- #endif
1178-
11791174/* instead of pfree'ing filename, remember it for next time */
11801175if (last_csv_file_name != NULL )
11811176pfree (last_csv_file_name );