Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 961ad3f

Browse files
committed
On Windows, syslogger runs in two threads. The main thread processes config
reload and rotation signals, and a helper thread reads messages from the pipe and writes them to the log file. However, server code isn't generally thread-safe, so if both try to do e.g palloc()/pfree() at the same time, bad things will happen. To fix that, use a critical section (which is like a mutex) to enforce that only one the threads are active at a time.
1 parent 78974cf commit 961ad3f

File tree

1 file changed

+28
-33
lines changed

1 file changed

+28
-33
lines changed

src/backend/postmaster/syslogger.c

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
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 @@ HANDLE syslogPipe[2] = {0, 0};
117117

118118
#ifdef WIN32
119119
static 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

273274
threadHandle = (HANDLE) _beginthreadex(NULL, 0, pipeThread, NULL, 0, NULL);
274275
if (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+
427434
pg_usleep(1000000L);
435+
436+
EnterCriticalSection(&sysloggerSection);
428437
#endif /* WIN32 */
429438

430439
if (pipe_eof_seen)
@@ -911,17 +920,9 @@ write_syslogger_file(const char *buffer, int count, int destination)
911920
if (destination == LOG_DESTINATION_CSVLOG && csvlogFile == NULL)
912921
open_csvlogfile();
913922

914-
#ifdef WIN32
915-
EnterCriticalSection(&sysfileSection);
916-
#endif
917-
918923
logfile = destination == LOG_DESTINATION_CSVLOG ? csvlogFile : syslogFile;
919924
rc = 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 */
926927
if (rc != count)
927928
write_stderr("could not write to log file: %s\n", strerror(errno));
@@ -945,11 +946,21 @@ pipeThread(void *arg)
945946
for (;;)
946947
{
947948
DWORD 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
{
954965
DWORD error = GetLastError();
955966

@@ -966,6 +977,7 @@ pipeThread(void *arg)
966977
bytes_in_logbuffer += bytesRead;
967978
process_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 */
975987
flush_pipe_input(logbuffer, &bytes_in_logbuffer);
976988

989+
LeaveCriticalSection(&sysloggerSection);
977990
_endthread();
978991
return 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-
11051113
fclose(syslogFile);
11061114
syslogFile = fh;
11071115

1108-
#ifdef WIN32
1109-
LeaveCriticalSection(&sysfileSection);
1110-
#endif
1111-
11121116
/* instead of pfree'ing filename, remember it for next time */
11131117
if (last_file_name != NULL)
11141118
pfree(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-
11721171
fclose(csvlogFile);
11731172
csvlogFile = fh;
11741173

1175-
#ifdef WIN32
1176-
LeaveCriticalSection(&sysfileSection);
1177-
#endif
1178-
11791174
/* instead of pfree'ing filename, remember it for next time */
11801175
if (last_csv_file_name != NULL)
11811176
pfree(last_csv_file_name);

0 commit comments

Comments
 (0)