PostgreSQL Source Code: src/backend/postmaster/syslogger.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
25
26#include <fcntl.h>
27#include <limits.h>
28#include <signal.h>
31#include <sys/stat.h>
33
54
55
56
57
58
59
60#define READ_BUF_SIZE (2 * PIPE_CHUNK_SIZE)
61
62
63#define LOGROTATE_SIGNAL_FILE "logrotate"
64
65
66
67
68
69
77
78
79
80
91
92
93
94
95
96
97
98
99
100
101
102
103typedef struct
104{
108
109#define NBUFFER_LISTS 256
111
112
113#ifndef WIN32
115#else
117#endif
118
119#ifdef WIN32
120static HANDLE threadHandle = 0;
121static CRITICAL_SECTION sysloggerSection;
122#endif
123
124
125
126
128
129
130
131#ifdef EXEC_BACKEND
132static int syslogger_fdget(FILE *file);
133static FILE *syslogger_fdopen(int fd);
134#endif
135static void process_pipe_input(char *logbuffer, int *bytes_in_logbuffer);
136static void flush_pipe_input(char *logbuffer, int *bytes_in_logbuffer);
138 bool allow_errors);
139
140#ifdef WIN32
141static unsigned int __stdcall pipeThread(void *arg);
142#endif
143static void logfile_rotate(bool time_based_rotation, int size_rotation_for);
145 int size_rotation_for, pg_time_t fntime,
146 int target_dest, char **last_file_name,
147 FILE **logFile);
152
153typedef struct
154{
159
160
161
162
163
164void
165SysLoggerMain(const void *startup_data, size_t startup_data_len)
166{
167#ifndef WIN32
169 int bytes_in_logbuffer = 0;
170#endif
171 char *currentLogDir;
172 char *currentLogFilename;
173 int currentLogRotationAge;
176
177
178
179
180
181
182
183
184#ifdef EXEC_BACKEND
185 {
187
188 Assert(startup_data_len == sizeof(*slsdata));
192 }
193#else
194 Assert(startup_data_len == 0);
195#endif
196
197
198
199
200
202 {
205 }
206
208
211
212
213
214
215
216
217
218
220 {
221 int fd = open(DEVNULL, O_WRONLY, 0);
222
223
224
225
226
227
228
229
230
231
232
233
236 if (fd != -1)
237 {
241 }
242 }
243
244
245
246
247
248
249#ifdef WIN32
250 else
252#endif
253
254
255
256
257
258
259#ifndef WIN32
263#else
267#endif
268
269
270
271
272
273
274
275
276
278
286
287
288
289
291
292 sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);
293
294#ifdef WIN32
295
296 InitializeCriticalSection(&sysloggerSection);
297 EnterCriticalSection(&sysloggerSection);
298
299 threadHandle = (HANDLE) _beginthreadex(NULL, 0, pipeThread, NULL, 0, NULL);
300 if (threadHandle == 0)
301 elog(FATAL, "could not create syslogger data transfer thread: %m");
302#endif
303
304
305
306
307
308
314
315
319
322
323
324
325
326
327
329
330
331
332
333
334
335
336
337
338
339
342#ifndef WIN32
344#endif
345
346
347 for (;;)
348 {
349 bool time_based_rotation = false;
350 int size_rotation_for = 0;
351 long cur_timeout;
353
354#ifndef WIN32
355 int rc;
356#endif
357
358
360
361
362
363
365 {
368
369
370
371
372
373
375 {
376 pfree(currentLogDir);
379
380
381
382
384 }
385 if (strcmp(Log_filename, currentLogFilename) != 0)
386 {
387 pfree(currentLogFilename);
390 }
391
392
393
394
395
399
400
401
402
403
407
408
409
410
411
413 {
416 }
417
418
419
420
421
423 {
426 }
427
428
429
430
431
432
434 }
435
437 {
438
442 }
443
445 {
446
448 {
451 }
454 {
457 }
460 {
463 }
464 }
465
467 {
468
469
470
471
472 if (!time_based_rotation && size_rotation_for == 0)
476 logfile_rotate(time_based_rotation, size_rotation_for);
477 }
478
479
480
481
482
483
484
485
486
487
488
489
490
492 {
494
496 if (delay > 0)
497 {
498 if (delay > INT_MAX / 1000)
499 delay = INT_MAX / 1000;
500 cur_timeout = delay * 1000L;
501 }
502 else
503 cur_timeout = 0;
504 }
505 else
506 cur_timeout = -1L;
507
508
509
510
511#ifndef WIN32
513 WAIT_EVENT_SYSLOGGER_MAIN);
514
516 {
517 int bytesRead;
518
520 logbuffer + bytes_in_logbuffer,
521 sizeof(logbuffer) - bytes_in_logbuffer);
522 if (bytesRead < 0)
523 {
524 if (errno != EINTR)
527 errmsg("could not read from logger pipe: %m")));
528 }
529 else if (bytesRead > 0)
530 {
531 bytes_in_logbuffer += bytesRead;
533 continue;
534 }
535 else
536 {
537
538
539
540
541
542
544
545
547 }
548 }
549#else
550
551
552
553
554
555
556
557
558
559
560 LeaveCriticalSection(&sysloggerSection);
561
563 WAIT_EVENT_SYSLOGGER_MAIN);
564
565 EnterCriticalSection(&sysloggerSection);
566#endif
567
569 {
570
571
572
573
576
577
578
579
580
581
582
583
585 }
586 }
587}
588
589
590
591
592int
594{
595 pid_t sysloggerPid;
597#ifdef EXEC_BACKEND
599#endif
600
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620#ifndef WIN32
622 {
626 errmsg("could not create pipe for syslog: %m")));
627 }
628#else
630 {
631 SECURITY_ATTRIBUTES sa;
632
633 memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
634 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
635 sa.bInheritHandle = TRUE;
636
640 errmsg("could not create pipe for syslog: %m")));
641 }
642#endif
643
644
645
646
648
649
650
651
652
653
654
655
656
657
658
659
660
662
664
666
668
669
670
671
672
673
675 {
677
679
681 }
682
683
684
685
686
687
689 {
691
693
695 }
696
697#ifdef EXEC_BACKEND
702 &startup_data, sizeof(startup_data), NULL);
703#else
705 NULL, 0, NULL);
706#endif
707
708 if (sysloggerPid == -1)
709 {
711 (errmsg("could not fork system logger: %m")));
712 return 0;
713 }
714
715
716
717
719 {
720#ifdef WIN32
721 int fd;
722#endif
723
724
725
726
727
728
730 (errmsg("redirecting log output to logging collector process"),
731 errhint("Future log output will appear in directory \"%s\".",
733
734#ifndef WIN32
739 errmsg("could not redirect stdout: %m")));
740 fflush(stderr);
744 errmsg("could not redirect stderr: %m")));
745
748#else
749
750
751
752
753
754
755 fflush(stderr);
756 fd = _open_osfhandle((intptr_t) syslogPipe[1],
757 _O_APPEND | _O_BINARY);
761 errmsg("could not redirect stderr: %m")));
764
765
766
767
768
769
771#endif
773 }
774
775
779 {
782 }
784 {
787 }
788 return (int) sysloggerPid;
789}
790
791
792#ifdef EXEC_BACKEND
793
794
795
796
797
798
799
800static int
801syslogger_fdget(FILE *file)
802{
803#ifndef WIN32
804 if (file != NULL)
805 return fileno(file);
806 else
807 return -1;
808#else
809 if (file != NULL)
810 return (int) _get_osfhandle(_fileno(file));
811 else
812 return 0;
813#endif
814}
815
816
817
818
819
820
821
822static FILE *
823syslogger_fdopen(int fd)
824{
825 FILE *file = NULL;
826
827#ifndef WIN32
828 if (fd != -1)
829 {
830 file = fdopen(fd, "a");
831 setvbuf(file, NULL, PG_IOLBF, 0);
832 }
833#else
834 if (fd != 0)
835 {
836 fd = _open_osfhandle(fd, _O_APPEND | _O_TEXT);
837 if (fd > 0)
838 {
839 file = fdopen(fd, "a");
840 setvbuf(file, NULL, PG_IOLBF, 0);
841 }
842 }
843#endif
844
845 return file;
846}
847#endif
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878static void
880{
881 char *cursor = logbuffer;
882 int count = *bytes_in_logbuffer;
884
885
887 {
889 int chunklen;
890 bits8 dest_flags;
891
892
897 if (p.nuls[0] == '\0' && p.nuls[1] == '\0' &&
899 p.pid != 0 &&
901 {
902 List *buffer_list;
905 *free_slot = NULL;
907
909
910
911 if (count < chunklen)
912 break;
913
920 else
921 {
922
924 }
925
926
928 foreach(cell, buffer_list)
929 {
931
933 {
934 existing_slot = buf;
935 break;
936 }
937 if (buf->pid == 0 && free_slot == NULL)
938 free_slot = buf;
939 }
940
942 {
943
944
945
946 if (existing_slot != NULL)
947 {
948
949 str = &(existing_slot->data);
953 }
954 else
955 {
956
957 if (free_slot == NULL)
958 {
959
960
961
962
964 buffer_list = lappend(buffer_list, free_slot);
966 }
967 free_slot->pid = p.pid;
968 str = &(free_slot->data);
973 }
974 }
975 else
976 {
977
978
979
980
981 if (existing_slot != NULL)
982 {
983 str = &(existing_slot->data);
988
989 existing_slot->pid = 0;
991 }
992 else
993 {
994
997 }
998 }
999
1000
1002 count -= chunklen;
1003 }
1004 else
1005 {
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017 for (chunklen = 1; chunklen < count; chunklen++)
1018 {
1019 if (cursor[chunklen] == '\0')
1020 break;
1021 }
1022
1025 count -= chunklen;
1026 }
1027 }
1028
1029
1030 if (count > 0 && cursor != logbuffer)
1031 memmove(logbuffer, cursor, count);
1032 *bytes_in_logbuffer = count;
1033}
1034
1035
1036
1037
1038
1039
1040
1041static void
1043{
1044 int i;
1045
1046
1048 {
1051
1052 foreach(cell, list)
1053 {
1055
1056 if (buf->pid != 0)
1057 {
1059
1062
1063 buf->pid = 0;
1065 }
1066 }
1067 }
1068
1069
1070
1071
1072
1073 if (*bytes_in_logbuffer > 0)
1076 *bytes_in_logbuffer = 0;
1077}
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092void
1094{
1095 int rc;
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1115 else
1117
1118 rc = fwrite(buffer, 1, count, logfile);
1119
1120
1121
1122
1123
1124
1125
1126 if (rc != count)
1127 write_stderr("could not write to log file: %m\n");
1128}
1129
1130#ifdef WIN32
1131
1132
1133
1134
1135
1136
1137
1138
1139static unsigned int __stdcall
1140pipeThread(void *arg)
1141{
1143 int bytes_in_logbuffer = 0;
1144
1145 for (;;)
1146 {
1147 DWORD bytesRead;
1148 BOOL result;
1149
1151 logbuffer + bytes_in_logbuffer,
1152 sizeof(logbuffer) - bytes_in_logbuffer,
1153 &bytesRead, 0);
1154
1155
1156
1157
1158
1159
1160
1161 EnterCriticalSection(&sysloggerSection);
1162 if (!result)
1163 {
1164 DWORD error = GetLastError();
1165
1166 if (error == ERROR_HANDLE_EOF ||
1167 error == ERROR_BROKEN_PIPE)
1168 break;
1172 errmsg("could not read from logger pipe: %m")));
1173 }
1174 else if (bytesRead > 0)
1175 {
1176 bytes_in_logbuffer += bytesRead;
1178 }
1179
1180
1181
1182
1183
1185 {
1192 }
1193 LeaveCriticalSection(&sysloggerSection);
1194 }
1195
1196
1198
1199
1201
1202
1204
1205 LeaveCriticalSection(&sysloggerSection);
1206 _endthread();
1207 return 0;
1208}
1209#endif
1210
1211
1212
1213
1214
1215
1216
1217
1218static FILE *
1220{
1221 FILE *fh;
1222 mode_t oumask;
1223
1224
1225
1226
1227
1230 umask(oumask);
1231
1232 if (fh)
1233 {
1234 setvbuf(fh, NULL, PG_IOLBF, 0);
1235
1236#ifdef WIN32
1237
1238 _setmode(_fileno(fh), _O_TEXT);
1239#endif
1240 }
1241 else
1242 {
1243 int save_errno = errno;
1244
1247 errmsg("could not open log file \"%s\": %m",
1249 errno = save_errno;
1250 }
1251
1252 return fh;
1253}
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263static bool
1265 pg_time_t fntime, int target_dest,
1266 char **last_file_name, FILE **logFile)
1267{
1268 char *logFileExt = NULL;
1270 FILE *fh;
1271
1272
1273
1274
1275
1276
1277
1280 {
1281 if (*logFile != NULL)
1282 fclose(*logFile);
1283 *logFile = NULL;
1284 if (*last_file_name != NULL)
1285 pfree(*last_file_name);
1286 *last_file_name = NULL;
1287 return true;
1288 }
1289
1290
1291
1292
1293
1294 if (!time_based_rotation && (size_rotation_for & target_dest) == 0)
1295 return true;
1296
1297
1299 logFileExt = NULL;
1301 logFileExt = ".csv";
1303 logFileExt = ".json";
1304 else
1305 {
1306
1308 }
1309
1310
1312
1313
1314
1315
1316
1317
1318
1320 *last_file_name != NULL &&
1321 strcmp(filename, *last_file_name) != 0)
1323 else
1325
1326 if (!fh)
1327 {
1328
1329
1330
1331
1332
1333
1334 if (errno != ENFILE && errno != EMFILE)
1335 {
1337 (errmsg("disabling automatic rotation (use SIGHUP to re-enable)")));
1339 }
1340
1343 return false;
1344 }
1345
1346
1347 if (*logFile != NULL)
1348 fclose(*logFile);
1349 *logFile = fh;
1350
1351
1352 if (*last_file_name != NULL)
1353 pfree(*last_file_name);
1355
1356 return true;
1357}
1358
1359
1360
1361
1362static void
1364{
1366
1368
1369
1370
1371
1372
1373
1374 if (time_based_rotation)
1376 else
1377 fntime = time(NULL);
1378
1379
1380 if ((time_based_rotation, size_rotation_for, fntime,
1383 return;
1384
1385
1386 if ((time_based_rotation, size_rotation_for, fntime,
1389 return;
1390
1391
1392 if ((time_based_rotation, size_rotation_for, fntime,
1395 return;
1396
1398
1400}
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411static char *
1413{
1415 int len;
1416
1418
1420
1422
1423
1426
1427 if (suffix != NULL)
1428 {
1430 if (len > 4 && (strcmp(filename + (len - 4), ".log") == 0))
1431 len -= 4;
1433 }
1434
1436}
1437
1438
1439
1440
1441static void
1443{
1446 int rotinterval;
1447
1448
1450 return;
1451
1452
1453
1454
1455
1456
1457
1462 now -= now % rotinterval;
1463 now += rotinterval;
1466}
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476static void
1478{
1479 FILE *fh;
1480 mode_t oumask;
1481
1485 {
1489 errmsg("could not remove file \"%s\": %m",
1491 return;
1492 }
1493
1494
1497 umask(oumask);
1498
1499 if (fh)
1500 {
1501 setvbuf(fh, NULL, PG_IOLBF, 0);
1502
1503#ifdef WIN32
1504
1505 _setmode(_fileno(fh), _O_TEXT);
1506#endif
1507 }
1508 else
1509 {
1512 errmsg("could not open file \"%s\": %m",
1514 return;
1515 }
1516
1518 {
1520 {
1523 errmsg("could not write file \"%s\": %m",
1525 fclose(fh);
1526 return;
1527 }
1528 }
1529
1531 {
1533 {
1536 errmsg("could not write file \"%s\": %m",
1538 fclose(fh);
1539 return;
1540 }
1541 }
1542
1544 {
1546 {
1549 errmsg("could not write file \"%s\": %m",
1551 fclose(fh);
1552 return;
1553 }
1554 }
1555 fclose(fh);
1556
1560 errmsg("could not rename file \"%s\" to \"%s\": %m",
1562}
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573bool
1575{
1576 struct stat stat_buf;
1577
1579 return true;
1580
1581 return false;
1582}
1583
1584
1585
1586
1587void
1589{
1591}
1592
1593
1594static void
1596{
1599}
Datum now(PG_FUNCTION_ARGS)
#define write_stderr(str)
#define fprintf(file, fmt, msg)
int errcode_for_socket_access(void)
int errmsg_internal(const char *fmt,...)
int errcode_for_file_access(void)
int errhint(const char *fmt,...)
int errmsg(const char *fmt,...)
#define LOG_DESTINATION_JSONLOG
#define LOG_DESTINATION_STDERR
#define ereport(elevel,...)
#define LOG_DESTINATION_CSVLOG
int MakePGDirectory(const char *directoryName)
void ProcessConfigFile(GucContext context)
Assert(PointerIsAligned(start, uint64))
volatile sig_atomic_t ConfigReloadPending
void SignalHandlerForConfigReload(SIGNAL_ARGS)
void SetLatch(Latch *latch)
void ResetLatch(Latch *latch)
pid_t postmaster_child_launch(BackendType child_type, int child_slot, const void *startup_data, size_t startup_data_len, ClientSocket *client_sock)
List * lappend(List *list, void *datum)
char * pstrdup(const char *in)
void pfree(void *pointer)
MemoryContext PostmasterContext
void MemoryContextDelete(MemoryContext context)
BackendType MyBackendType
PGDLLIMPORT const uint8 pg_number_of_ones[256]
static PgChecksumMode mode
size_t pg_strftime(char *s, size_t maxsize, const char *format, const struct pg_tm *t)
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
PGDLLIMPORT pg_tz * log_timezone
size_t strlcpy(char *dst, const char *src, size_t siz)
CommandDest whereToSendOutput
static int fd(const char *x, int i)
void init_ps_display(const char *fixed_part)
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
void initStringInfo(StringInfo str)
bool Log_truncate_on_rotation
static bool rotation_disabled
static void logfile_rotate(bool time_based_rotation, int size_rotation_for)
static bool pipe_eof_seen
void SysLoggerMain(const void *startup_data, size_t startup_data_len)
static bool logfile_rotate_dest(bool time_based_rotation, int size_rotation_for, pg_time_t fntime, int target_dest, char **last_file_name, FILE **logFile)
bool CheckLogrotateSignal(void)
static char * logfile_getname(pg_time_t timestamp, const char *suffix)
#define LOGROTATE_SIGNAL_FILE
static FILE * logfile_open(const char *filename, const char *mode, bool allow_errors)
static void update_metainfo_datafile(void)
static char * last_csv_file_name
NON_EXEC_STATIC pg_time_t first_syslogger_file_time
static void process_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
void RemoveLogrotateSignalFiles(void)
void write_syslogger_file(const char *buffer, int count, int destination)
static pg_time_t next_rotation_time
static volatile sig_atomic_t rotation_requested
static List * buffer_lists[NBUFFER_LISTS]
static void sigUsr1Handler(SIGNAL_ARGS)
static void set_next_rotation_time(void)
static void flush_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
int SysLogger_Start(int child_slot)
static FILE * jsonlogFile
static char * last_json_file_name
static char * last_sys_file_name
#define PIPE_PROTO_DEST_JSONLOG
#define PIPE_PROTO_IS_LAST
#define PIPE_PROTO_DEST_CSVLOG
#define LOG_METAINFO_DATAFILE_TMP
#define PIPE_PROTO_DEST_STDERR
#define LOG_METAINFO_DATAFILE
int AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, Latch *latch, void *user_data)
int WaitEventSetWait(WaitEventSet *set, long timeout, WaitEvent *occurred_events, int nevents, uint32 wait_event_info)
WaitEventSet * CreateWaitEventSet(ResourceOwner resowner, int nevents)
#define WL_SOCKET_READABLE
void _dosmaperr(unsigned long)