PostgreSQL Source Code  git master
syslogger.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * syslogger.c
4  *
5  * The system logger (syslogger) appeared in Postgres 8.0. It catches all
6  * stderr output from the postmaster, backends, and other subprocesses
7  * by redirecting to a pipe, and writes it to a set of logfiles.
8  * It's possible to have size and age limits for the logfile configured
9  * in postgresql.conf. If these limits are reached or passed, the
10  * current logfile is closed and a new one is created (rotated).
11  * The logfiles are stored in a subdirectory (configurable in
12  * postgresql.conf), using a user-selectable naming scheme.
13  *
14  * Author: Andreas Pflug <pgadmin@pse-consulting.de>
15  *
16  * Copyright (c) 2004-2020, PostgreSQL Global Development Group
17  *
18  *
19  * IDENTIFICATION
20  * src/backend/postmaster/syslogger.c
21  *
22  *-------------------------------------------------------------------------
23  */
24 #include "postgres.h"
25 
26 #include <fcntl.h>
27 #include <limits.h>
28 #include <signal.h>
29 #include <time.h>
30 #include <unistd.h>
31 #include <sys/stat.h>
32 #include <sys/time.h>
33 
34 #include "common/file_perm.h"
35 #include "lib/stringinfo.h"
36 #include "libpq/pqsignal.h"
37 #include "miscadmin.h"
38 #include "nodes/pg_list.h"
39 #include "pgstat.h"
40 #include "pgtime.h"
42 #include "postmaster/interrupt.h"
43 #include "postmaster/postmaster.h"
44 #include "postmaster/syslogger.h"
45 #include "storage/dsm.h"
46 #include "storage/fd.h"
47 #include "storage/ipc.h"
48 #include "storage/latch.h"
49 #include "storage/pg_shmem.h"
50 #include "tcop/tcopprot.h"
51 #include "utils/guc.h"
52 #include "utils/ps_status.h"
53 #include "utils/timestamp.h"
54 
55 /*
56  * We read() into a temp buffer twice as big as a chunk, so that any fragment
57  * left after processing can be moved down to the front and we'll still have
58  * room to read a full chunk.
59  */
60 #define READ_BUF_SIZE (2 * PIPE_CHUNK_SIZE)
61 
62 /* Log rotation signal file path, relative to $PGDATA */
63 #define LOGROTATE_SIGNAL_FILE "logrotate"
64 
65 
66 /*
67  * GUC parameters. Logging_collector cannot be changed after postmaster
68  * start, but the rest can change at SIGHUP.
69  */
70 bool Logging_collector = false;
72 int Log_RotationSize = 10 * 1024;
73 char *Log_directory = NULL;
74 char *Log_filename = NULL;
77 
78 extern bool redirection_done;
79 
80 /*
81  * Private state
82  */
84 static bool pipe_eof_seen = false;
85 static bool rotation_disabled = false;
86 static FILE *syslogFile = NULL;
87 static FILE *csvlogFile = NULL;
89 static char *last_file_name = NULL;
90 static char *last_csv_file_name = NULL;
91 
92 /*
93  * Buffers for saving partial messages from different backends.
94  *
95  * Keep NBUFFER_LISTS lists of these, with the entry for a given source pid
96  * being in the list numbered (pid % NBUFFER_LISTS), so as to cut down on
97  * the number of entries we have to examine for any one incoming message.
98  * There must never be more than one entry for the same source pid.
99  *
100  * An inactive buffer is not removed from its list, just held for re-use.
101  * An inactive buffer has pid == 0 and undefined contents of data.
102  */
103 typedef struct
104 {
105  int32 pid; /* PID of source process */
106  StringInfoData data; /* accumulated data, as a StringInfo */
107 } save_buffer;
108 
109 #define NBUFFER_LISTS 256
111 
112 /* These must be exported for EXEC_BACKEND case ... annoying */
113 #ifndef WIN32
114 int syslogPipe[2] = {-1, -1};
115 #else
116 HANDLE syslogPipe[2] = {0, 0};
117 #endif
118 
119 #ifdef WIN32
120 static HANDLE threadHandle = 0;
121 static CRITICAL_SECTION sysloggerSection;
122 #endif
123 
124 /*
125  * Flags set by interrupt handlers for later service in the main loop.
126  */
127 static volatile sig_atomic_t rotation_requested = false;
128 
129 
130 /* Local subroutines */
131 #ifdef EXEC_BACKEND
132 static pid_t syslogger_forkexec(void);
133 static void syslogger_parseArgs(int argc, char *argv[]);
134 #endif
135 NON_EXEC_STATIC void SysLoggerMain(int argc, char *argv[]) pg_attribute_noreturn();
136 static void process_pipe_input(char *logbuffer, int *bytes_in_logbuffer);
137 static void flush_pipe_input(char *logbuffer, int *bytes_in_logbuffer);
138 static FILE *logfile_open(const char *filename, const char *mode,
139  bool allow_errors);
140 
141 #ifdef WIN32
142 static unsigned int __stdcall pipeThread(void *arg);
143 #endif
144 static void logfile_rotate(bool time_based_rotation, int size_rotation_for);
145 static char *logfile_getname(pg_time_t timestamp, const char *suffix);
146 static void set_next_rotation_time(void);
147 static void sigUsr1Handler(SIGNAL_ARGS);
148 static void update_metainfo_datafile(void);
149 
150 
151 /*
152  * Main entry point for syslogger process
153  * argc/argv parameters are valid only in EXEC_BACKEND case.
154  */
155 NON_EXEC_STATIC void
156 SysLoggerMain(int argc, char *argv[])
157 {
158 #ifndef WIN32
159  char logbuffer[READ_BUF_SIZE];
160  int bytes_in_logbuffer = 0;
161 #endif
162  char *currentLogDir;
163  char *currentLogFilename;
164  int currentLogRotationAge;
165  pg_time_t now;
166  WaitEventSet *wes;
167 
168  now = MyStartTime;
169 
170 #ifdef EXEC_BACKEND
171  syslogger_parseArgs(argc, argv);
172 #endif /* EXEC_BACKEND */
173 
175  init_ps_display(NULL);
176 
177  /*
178  * If we restarted, our stderr is already redirected into our own input
179  * pipe. This is of course pretty useless, not to mention that it
180  * interferes with detecting pipe EOF. Point stderr to /dev/null. This
181  * assumes that all interesting messages generated in the syslogger will
182  * come through elog.c and will be sent to write_syslogger_file.
183  */
184  if (redirection_done)
185  {
186  int fd = open(DEVNULL, O_WRONLY, 0);
187 
188  /*
189  * The closes might look redundant, but they are not: we want to be
190  * darn sure the pipe gets closed even if the open failed. We can
191  * survive running with stderr pointing nowhere, but we can't afford
192  * to have extra pipe input descriptors hanging around.
193  *
194  * As we're just trying to reset these to go to DEVNULL, there's not
195  * much point in checking for failure from the close/dup2 calls here,
196  * if they fail then presumably the file descriptors are closed and
197  * any writes will go into the bitbucket anyway.
198  */
199  close(fileno(stdout));
200  close(fileno(stderr));
201  if (fd != -1)
202  {
203  (void) dup2(fd, fileno(stdout));
204  (void) dup2(fd, fileno(stderr));
205  close(fd);
206  }
207  }
208 
209  /*
210  * Syslogger's own stderr can't be the syslogPipe, so set it back to text
211  * mode if we didn't just close it. (It was set to binary in
212  * SubPostmasterMain).
213  */
214 #ifdef WIN32
215  else
216  _setmode(_fileno(stderr), _O_TEXT);
217 #endif
218 
219  /*
220  * Also close our copy of the write end of the pipe. This is needed to
221  * ensure we can detect pipe EOF correctly. (But note that in the restart
222  * case, the postmaster already did this.)
223  */
224 #ifndef WIN32
225  if (syslogPipe[1] >= 0)
226  close(syslogPipe[1]);
227  syslogPipe[1] = -1;
228 #else
229  if (syslogPipe[1])
230  CloseHandle(syslogPipe[1]);
231  syslogPipe[1] = 0;
232 #endif
233 
234  /*
235  * Properly accept or ignore signals the postmaster might send us
236  *
237  * Note: we ignore all termination signals, and instead exit only when all
238  * upstream processes are gone, to ensure we don't miss any dying gasps of
239  * broken backends...
240  */
241 
242  pqsignal(SIGHUP, SignalHandlerForConfigReload); /* set flag to read config file */
243  pqsignal(SIGINT, SIG_IGN);
244  pqsignal(SIGTERM, SIG_IGN);
248  pqsignal(SIGUSR1, sigUsr1Handler); /* request log rotation */
250 
251  /*
252  * Reset some signals that are accepted by postmaster but not here
253  */
255 
257 
258 #ifdef WIN32
259  /* Fire up separate data transfer thread */
260  InitializeCriticalSection(&sysloggerSection);
261  EnterCriticalSection(&sysloggerSection);
262 
263  threadHandle = (HANDLE) _beginthreadex(NULL, 0, pipeThread, NULL, 0, NULL);
264  if (threadHandle == 0)
265  elog(FATAL, "could not create syslogger data transfer thread: %m");
266 #endif /* WIN32 */
267 
268  /*
269  * Remember active logfiles' name(s). We recompute 'em from the reference
270  * time because passing down just the pg_time_t is a lot cheaper than
271  * passing a whole file path in the EXEC_BACKEND case.
272  */
274  if (csvlogFile != NULL)
276 
277  /* remember active logfile parameters */
278  currentLogDir = pstrdup(Log_directory);
279  currentLogFilename = pstrdup(Log_filename);
280  currentLogRotationAge = Log_RotationAge;
281  /* set next planned rotation time */
284 
285  /*
286  * Reset whereToSendOutput, as the postmaster will do (but hasn't yet, at
287  * the point where we forked). This prevents duplicate output of messages
288  * from syslogger itself.
289  */
291 
292  /*
293  * Set up a reusable WaitEventSet object we'll use to wait for our latch,
294  * and (except on Windows) our socket.
295  *
296  * Unlike all other postmaster child processes, we'll ignore postmaster
297  * death because we want to collect final log output from all backends and
298  * then exit last. We'll do that by running until we see EOF on the
299  * syslog pipe, which implies that all other backends have exited
300  * (including the postmaster).
301  */
304 #ifndef WIN32
305  AddWaitEventToSet(wes, WL_SOCKET_READABLE, syslogPipe[0], NULL, NULL);
306 #endif
307 
308  /* main worker loop */
309  for (;;)
310  {
311  bool time_based_rotation = false;
312  int size_rotation_for = 0;
313  long cur_timeout;
314  WaitEvent event;
315 
316 #ifndef WIN32
317  int rc;
318 #endif
319 
320  /* Clear any already-pending wakeups */
322 
323  /*
324  * Process any requests or signals received recently.
325  */
327  {
328  ConfigReloadPending = false;
330 
331  /*
332  * Check if the log directory or filename pattern changed in
333  * postgresql.conf. If so, force rotation to make sure we're
334  * writing the logfiles in the right place.
335  */
336  if (strcmp(Log_directory, currentLogDir) != 0)
337  {
338  pfree(currentLogDir);
339  currentLogDir = pstrdup(Log_directory);
340  rotation_requested = true;
341 
342  /*
343  * Also, create new directory if not present; ignore errors
344  */
346  }
347  if (strcmp(Log_filename, currentLogFilename) != 0)
348  {
349  pfree(currentLogFilename);
350  currentLogFilename = pstrdup(Log_filename);
351  rotation_requested = true;
352  }
353 
354  /*
355  * Force a rotation if CSVLOG output was just turned on or off and
356  * we need to open or close csvlogFile accordingly.
357  */
358  if (((Log_destination & LOG_DESTINATION_CSVLOG) != 0) !=
359  (csvlogFile != NULL))
360  rotation_requested = true;
361 
362  /*
363  * If rotation time parameter changed, reset next rotation time,
364  * but don't immediately force a rotation.
365  */
366  if (currentLogRotationAge != Log_RotationAge)
367  {
368  currentLogRotationAge = Log_RotationAge;
370  }
371 
372  /*
373  * If we had a rotation-disabling failure, re-enable rotation
374  * attempts after SIGHUP, and force one immediately.
375  */
376  if (rotation_disabled)
377  {
378  rotation_disabled = false;
379  rotation_requested = true;
380  }
381 
382  /*
383  * Force rewriting last log filename when reloading configuration.
384  * Even if rotation_requested is false, log_destination may have
385  * been changed and we don't want to wait the next file rotation.
386  */
388  }
389 
391  {
392  /* Do a logfile rotation if it's time */
393  now = (pg_time_t) time(NULL);
394  if (now >= next_rotation_time)
395  rotation_requested = time_based_rotation = true;
396  }
397 
399  {
400  /* Do a rotation if file is too big */
401  if (ftell(syslogFile) >= Log_RotationSize * 1024L)
402  {
403  rotation_requested = true;
404  size_rotation_for |= LOG_DESTINATION_STDERR;
405  }
406  if (csvlogFile != NULL &&
407  ftell(csvlogFile) >= Log_RotationSize * 1024L)
408  {
409  rotation_requested = true;
410  size_rotation_for |= LOG_DESTINATION_CSVLOG;
411  }
412  }
413 
414  if (rotation_requested)
415  {
416  /*
417  * Force rotation when both values are zero. It means the request
418  * was sent by pg_rotate_logfile() or "pg_ctl logrotate".
419  */
420  if (!time_based_rotation && size_rotation_for == 0)
421  size_rotation_for = LOG_DESTINATION_STDERR | LOG_DESTINATION_CSVLOG;
422  logfile_rotate(time_based_rotation, size_rotation_for);
423  }
424 
425  /*
426  * Calculate time till next time-based rotation, so that we don't
427  * sleep longer than that. We assume the value of "now" obtained
428  * above is still close enough. Note we can't make this calculation
429  * until after calling logfile_rotate(), since it will advance
430  * next_rotation_time.
431  *
432  * Also note that we need to beware of overflow in calculation of the
433  * timeout: with large settings of Log_RotationAge, next_rotation_time
434  * could be more than INT_MAX msec in the future. In that case we'll
435  * wait no more than INT_MAX msec, and try again.
436  */
438  {
439  pg_time_t delay;
440 
441  delay = next_rotation_time - now;
442  if (delay > 0)
443  {
444  if (delay > INT_MAX / 1000)
445  delay = INT_MAX / 1000;
446  cur_timeout = delay * 1000L; /* msec */
447  }
448  else
449  cur_timeout = 0;
450  }
451  else
452  cur_timeout = -1L;
453 
454  /*
455  * Sleep until there's something to do
456  */
457 #ifndef WIN32
458  rc = WaitEventSetWait(wes, cur_timeout, &event, 1,
460 
461  if (rc == 1 && event.events == WL_SOCKET_READABLE)
462  {
463  int bytesRead;
464 
465  bytesRead = read(syslogPipe[0],
466  logbuffer + bytes_in_logbuffer,
467  sizeof(logbuffer) - bytes_in_logbuffer);
468  if (bytesRead < 0)
469  {
470  if (errno != EINTR)
471  ereport(LOG,
473  errmsg("could not read from logger pipe: %m")));
474  }
475  else if (bytesRead > 0)
476  {
477  bytes_in_logbuffer += bytesRead;
478  process_pipe_input(logbuffer, &bytes_in_logbuffer);
479  continue;
480  }
481  else
482  {
483  /*
484  * Zero bytes read when select() is saying read-ready means
485  * EOF on the pipe: that is, there are no longer any processes
486  * with the pipe write end open. Therefore, the postmaster
487  * and all backends are shut down, and we are done.
488  */
489  pipe_eof_seen = true;
490 
491  /* if there's any data left then force it out now */
492  flush_pipe_input(logbuffer, &bytes_in_logbuffer);
493  }
494  }
495 #else /* WIN32 */
496 
497  /*
498  * On Windows we leave it to a separate thread to transfer data and
499  * detect pipe EOF. The main thread just wakes up to handle SIGHUP
500  * and rotation conditions.
501  *
502  * Server code isn't generally thread-safe, so we ensure that only one
503  * of the threads is active at a time by entering the critical section
504  * whenever we're not sleeping.
505  */
506  LeaveCriticalSection(&sysloggerSection);
507 
508  (void) WaitEventSetWait(wes, cur_timeout, &event, 1,
510 
511  EnterCriticalSection(&sysloggerSection);
512 #endif /* WIN32 */
513 
514  if (pipe_eof_seen)
515  {
516  /*
517  * seeing this message on the real stderr is annoying - so we make
518  * it DEBUG1 to suppress in normal use.
519  */
520  ereport(DEBUG1,
521  (errmsg("logger shutting down")));
522 
523  /*
524  * Normal exit from the syslogger is here. Note that we
525  * deliberately do not close syslogFile before exiting; this is to
526  * allow for the possibility of elog messages being generated
527  * inside proc_exit. Regular exit() will take care of flushing
528  * and closing stdio channels.
529  */
530  proc_exit(0);
531  }
532  }
533 }
534 
535 /*
536  * Postmaster subroutine to start a syslogger subprocess.
537  */
538 int
540 {
541  pid_t sysloggerPid;
542  char *filename;
543 
544  if (!Logging_collector)
545  return 0;
546 
547  /*
548  * If first time through, create the pipe which will receive stderr
549  * output.
550  *
551  * If the syslogger crashes and needs to be restarted, we continue to use
552  * the same pipe (indeed must do so, since extant backends will be writing
553  * into that pipe).
554  *
555  * This means the postmaster must continue to hold the read end of the
556  * pipe open, so we can pass it down to the reincarnated syslogger. This
557  * is a bit klugy but we have little choice.
558  *
559  * Also note that we don't bother counting the pipe FDs by calling
560  * Reserve/ReleaseExternalFD. There's no real need to account for them
561  * accurately in the postmaster or syslogger process, and both ends of the
562  * pipe will wind up closed in all other postmaster children.
563  */
564 #ifndef WIN32
565  if (syslogPipe[0] < 0)
566  {
567  if (pipe(syslogPipe) < 0)
568  ereport(FATAL,
570  errmsg("could not create pipe for syslog: %m")));
571  }
572 #else
573  if (!syslogPipe[0])
574  {
575  SECURITY_ATTRIBUTES sa;
576 
577  memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
578  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
579  sa.bInheritHandle = TRUE;
580 
581  if (!CreatePipe(&syslogPipe[0], &syslogPipe[1], &sa, 32768))
582  ereport(FATAL,
584  errmsg("could not create pipe for syslog: %m")));
585  }
586 #endif
587 
588  /*
589  * Create log directory if not present; ignore errors
590  */
592 
593  /*
594  * The initial logfile is created right in the postmaster, to verify that
595  * the Log_directory is writable. We save the reference time so that the
596  * syslogger child process can recompute this file name.
597  *
598  * It might look a bit strange to re-do this during a syslogger restart,
599  * but we must do so since the postmaster closed syslogFile after the
600  * previous fork (and remembering that old file wouldn't be right anyway).
601  * Note we always append here, we won't overwrite any existing file. This
602  * is consistent with the normal rules, because by definition this is not
603  * a time-based rotation.
604  */
605  first_syslogger_file_time = time(NULL);
606 
607  filename = logfile_getname(first_syslogger_file_time, NULL);
608 
609  syslogFile = logfile_open(filename, "a", false);
610 
611  pfree(filename);
612 
613  /*
614  * Likewise for the initial CSV log file, if that's enabled. (Note that
615  * we open syslogFile even when only CSV output is nominally enabled,
616  * since some code paths will write to syslogFile anyway.)
617  */
619  {
620  filename = logfile_getname(first_syslogger_file_time, ".csv");
621 
622  csvlogFile = logfile_open(filename, "a", false);
623 
624  pfree(filename);
625  }
626 
627 #ifdef EXEC_BACKEND
628  switch ((sysloggerPid = syslogger_forkexec()))
629 #else
630  switch ((sysloggerPid = fork_process()))
631 #endif
632  {
633  case -1:
634  ereport(LOG,
635  (errmsg("could not fork system logger: %m")));
636  return 0;
637 
638 #ifndef EXEC_BACKEND
639  case 0:
640  /* in postmaster child ... */
642 
643  /* Close the postmaster's sockets */
644  ClosePostmasterPorts(true);
645 
646  /* Drop our connection to postmaster's shared memory, as well */
647  dsm_detach_all();
649 
650  /* do the work */
651  SysLoggerMain(0, NULL);
652  break;
653 #endif
654 
655  default:
656  /* success, in postmaster */
657 
658  /* now we redirect stderr, if not done already */
659  if (!redirection_done)
660  {
661 #ifdef WIN32
662  int fd;
663 #endif
664 
665  /*
666  * Leave a breadcrumb trail when redirecting, in case the user
667  * forgets that redirection is active and looks only at the
668  * original stderr target file.
669  */
670  ereport(LOG,
671  (errmsg("redirecting log output to logging collector process"),
672  errhint("Future log output will appear in directory \"%s\".",
673  Log_directory)));
674 
675 #ifndef WIN32
676  fflush(stdout);
677  if (dup2(syslogPipe[1], fileno(stdout)) < 0)
678  ereport(FATAL,
680  errmsg("could not redirect stdout: %m")));
681  fflush(stderr);
682  if (dup2(syslogPipe[1], fileno(stderr)) < 0)
683  ereport(FATAL,
685  errmsg("could not redirect stderr: %m")));
686  /* Now we are done with the write end of the pipe. */
687  close(syslogPipe[1]);
688  syslogPipe[1] = -1;
689 #else
690 
691  /*
692  * open the pipe in binary mode and make sure stderr is binary
693  * after it's been dup'ed into, to avoid disturbing the pipe
694  * chunking protocol.
695  */
696  fflush(stderr);
697  fd = _open_osfhandle((intptr_t) syslogPipe[1],
698  _O_APPEND | _O_BINARY);
699  if (dup2(fd, _fileno(stderr)) < 0)
700  ereport(FATAL,
702  errmsg("could not redirect stderr: %m")));
703  close(fd);
704  _setmode(_fileno(stderr), _O_BINARY);
705 
706  /*
707  * Now we are done with the write end of the pipe.
708  * CloseHandle() must not be called because the preceding
709  * close() closes the underlying handle.
710  */
711  syslogPipe[1] = 0;
712 #endif
713  redirection_done = true;
714  }
715 
716  /* postmaster will never write the file(s); close 'em */
717  fclose(syslogFile);
718  syslogFile = NULL;
719  if (csvlogFile != NULL)
720  {
721  fclose(csvlogFile);
722  csvlogFile = NULL;
723  }
724  return (int) sysloggerPid;
725  }
726 
727  /* we should never reach here */
728  return 0;
729 }
730 
731 
732 #ifdef EXEC_BACKEND
733 
734 /*
735  * syslogger_forkexec() -
736  *
737  * Format up the arglist for, then fork and exec, a syslogger process
738  */
739 static pid_t
740 syslogger_forkexec(void)
741 {
742  char *av[10];
743  int ac = 0;
744  char filenobuf[32];
745  char csvfilenobuf[32];
746 
747  av[ac++] = "postgres";
748  av[ac++] = "--forklog";
749  av[ac++] = NULL; /* filled in by postmaster_forkexec */
750 
751  /* static variables (those not passed by write_backend_variables) */
752 #ifndef WIN32
753  if (syslogFile != NULL)
754  snprintf(filenobuf, sizeof(filenobuf), "%d",
755  fileno(syslogFile));
756  else
757  strcpy(filenobuf, "-1");
758 #else /* WIN32 */
759  if (syslogFile != NULL)
760  snprintf(filenobuf, sizeof(filenobuf), "%ld",
761  (long) _get_osfhandle(_fileno(syslogFile)));
762  else
763  strcpy(filenobuf, "0");
764 #endif /* WIN32 */
765  av[ac++] = filenobuf;
766 
767 #ifndef WIN32
768  if (csvlogFile != NULL)
769  snprintf(csvfilenobuf, sizeof(csvfilenobuf), "%d",
770  fileno(csvlogFile));
771  else
772  strcpy(csvfilenobuf, "-1");
773 #else /* WIN32 */
774  if (csvlogFile != NULL)
775  snprintf(csvfilenobuf, sizeof(csvfilenobuf), "%ld",
776  (long) _get_osfhandle(_fileno(csvlogFile)));
777  else
778  strcpy(csvfilenobuf, "0");
779 #endif /* WIN32 */
780  av[ac++] = csvfilenobuf;
781 
782  av[ac] = NULL;
783  Assert(ac < lengthof(av));
784 
785  return postmaster_forkexec(ac, av);
786 }
787 
788 /*
789  * syslogger_parseArgs() -
790  *
791  * Extract data from the arglist for exec'ed syslogger process
792  */
793 static void
794 syslogger_parseArgs(int argc, char *argv[])
795 {
796  int fd;
797 
798  Assert(argc == 5);
799  argv += 3;
800 
801  /*
802  * Re-open the error output files that were opened by SysLogger_Start().
803  *
804  * We expect this will always succeed, which is too optimistic, but if it
805  * fails there's not a lot we can do to report the problem anyway. As
806  * coded, we'll just crash on a null pointer dereference after failure...
807  */
808 #ifndef WIN32
809  fd = atoi(*argv++);
810  if (fd != -1)
811  {
812  syslogFile = fdopen(fd, "a");
813  setvbuf(syslogFile, NULL, PG_IOLBF, 0);
814  }
815  fd = atoi(*argv++);
816  if (fd != -1)
817  {
818  csvlogFile = fdopen(fd, "a");
819  setvbuf(csvlogFile, NULL, PG_IOLBF, 0);
820  }
821 #else /* WIN32 */
822  fd = atoi(*argv++);
823  if (fd != 0)
824  {
825  fd = _open_osfhandle(fd, _O_APPEND | _O_TEXT);
826  if (fd > 0)
827  {
828  syslogFile = fdopen(fd, "a");
829  setvbuf(syslogFile, NULL, PG_IOLBF, 0);
830  }
831  }
832  fd = atoi(*argv++);
833  if (fd != 0)
834  {
835  fd = _open_osfhandle(fd, _O_APPEND | _O_TEXT);
836  if (fd > 0)
837  {
838  csvlogFile = fdopen(fd, "a");
839  setvbuf(csvlogFile, NULL, PG_IOLBF, 0);
840  }
841  }
842 #endif /* WIN32 */
843 }
844 #endif /* EXEC_BACKEND */
845 
846 
847 /* --------------------------------
848  * pipe protocol handling
849  * --------------------------------
850  */
851 
852 /*
853  * Process data received through the syslogger pipe.
854  *
855  * This routine interprets the log pipe protocol which sends log messages as
856  * (hopefully atomic) chunks - such chunks are detected and reassembled here.
857  *
858  * The protocol has a header that starts with two nul bytes, then has a 16 bit
859  * length, the pid of the sending process, and a flag to indicate if it is
860  * the last chunk in a message. Incomplete chunks are saved until we read some
861  * more, and non-final chunks are accumulated until we get the final chunk.
862  *
863  * All of this is to avoid 2 problems:
864  * . partial messages being written to logfiles (messes rotation), and
865  * . messages from different backends being interleaved (messages garbled).
866  *
867  * Any non-protocol messages are written out directly. These should only come
868  * from non-PostgreSQL sources, however (e.g. third party libraries writing to
869  * stderr).
870  *
871  * logbuffer is the data input buffer, and *bytes_in_logbuffer is the number
872  * of bytes present. On exit, any not-yet-eaten data is left-justified in
873  * logbuffer, and *bytes_in_logbuffer is updated.
874  */
875 static void
876 process_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
877 {
878  char *cursor = logbuffer;
879  int count = *bytes_in_logbuffer;
881 
882  /* While we have enough for a header, process data... */
883  while (count >= (int) (offsetof(PipeProtoHeader, data) + 1))
884  {
885  PipeProtoHeader p;
886  int chunklen;
887 
888  /* Do we have a valid header? */
889  memcpy(&p, cursor, offsetof(PipeProtoHeader, data));
890  if (p.nuls[0] == '\0' && p.nuls[1] == '\0' &&
891  p.len > 0 && p.len <= PIPE_MAX_PAYLOAD &&
892  p.pid != 0 &&
893  (p.is_last == 't' || p.is_last == 'f' ||
894  p.is_last == 'T' || p.is_last == 'F'))
895  {
896  List *buffer_list;
897  ListCell *cell;
898  save_buffer *existing_slot = NULL,
899  *free_slot = NULL;
900  StringInfo str;
901 
902  chunklen = PIPE_HEADER_SIZE + p.len;
903 
904  /* Fall out of loop if we don't have the whole chunk yet */
905  if (count < chunklen)
906  break;
907 
908  dest = (p.is_last == 'T' || p.is_last == 'F') ?
910 
911  /* Locate any existing buffer for this source pid */
912  buffer_list = buffer_lists[p.pid % NBUFFER_LISTS];
913  foreach(cell, buffer_list)
914  {
915  save_buffer *buf = (save_buffer *) lfirst(cell);
916 
917  if (buf->pid == p.pid)
918  {
919  existing_slot = buf;
920  break;
921  }
922  if (buf->pid == 0 && free_slot == NULL)
923  free_slot = buf;
924  }
925 
926  if (p.is_last == 'f' || p.is_last == 'F')
927  {
928  /*
929  * Save a complete non-final chunk in a per-pid buffer
930  */
931  if (existing_slot != NULL)
932  {
933  /* Add chunk to data from preceding chunks */
934  str = &(existing_slot->data);
936  cursor + PIPE_HEADER_SIZE,
937  p.len);
938  }
939  else
940  {
941  /* First chunk of message, save in a new buffer */
942  if (free_slot == NULL)
943  {
944  /*
945  * Need a free slot, but there isn't one in the list,
946  * so create a new one and extend the list with it.
947  */
948  free_slot = palloc(sizeof(save_buffer));
949  buffer_list = lappend(buffer_list, free_slot);
950  buffer_lists[p.pid % NBUFFER_LISTS] = buffer_list;
951  }
952  free_slot->pid = p.pid;
953  str = &(free_slot->data);
954  initStringInfo(str);
956  cursor + PIPE_HEADER_SIZE,
957  p.len);
958  }
959  }
960  else
961  {
962  /*
963  * Final chunk --- add it to anything saved for that pid, and
964  * either way write the whole thing out.
965  */
966  if (existing_slot != NULL)
967  {
968  str = &(existing_slot->data);
970  cursor + PIPE_HEADER_SIZE,
971  p.len);
972  write_syslogger_file(str->data, str->len, dest);
973  /* Mark the buffer unused, and reclaim string storage */
974  existing_slot->pid = 0;
975  pfree(str->data);
976  }
977  else
978  {
979  /* The whole message was one chunk, evidently. */
981  dest);
982  }
983  }
984 
985  /* Finished processing this chunk */
986  cursor += chunklen;
987  count -= chunklen;
988  }
989  else
990  {
991  /* Process non-protocol data */
992 
993  /*
994  * Look for the start of a protocol header. If found, dump data
995  * up to there and repeat the loop. Otherwise, dump it all and
996  * fall out of the loop. (Note: we want to dump it all if at all
997  * possible, so as to avoid dividing non-protocol messages across
998  * logfiles. We expect that in many scenarios, a non-protocol
999  * message will arrive all in one read(), and we want to respect
1000  * the read() boundary if possible.)
1001  */
1002  for (chunklen = 1; chunklen < count; chunklen++)
1003  {
1004  if (cursor[chunklen] == '\0')
1005  break;
1006  }
1007  /* fall back on the stderr log as the destination */
1008  write_syslogger_file(cursor, chunklen, LOG_DESTINATION_STDERR);
1009  cursor += chunklen;
1010  count -= chunklen;
1011  }
1012  }
1013 
1014  /* We don't have a full chunk, so left-align what remains in the buffer */
1015  if (count > 0 && cursor != logbuffer)
1016  memmove(logbuffer, cursor, count);
1017  *bytes_in_logbuffer = count;
1018 }
1019 
1020 /*
1021  * Force out any buffered data
1022  *
1023  * This is currently used only at syslogger shutdown, but could perhaps be
1024  * useful at other times, so it is careful to leave things in a clean state.
1025  */
1026 static void
1027 flush_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
1028 {
1029  int i;
1030 
1031  /* Dump any incomplete protocol messages */
1032  for (i = 0; i < NBUFFER_LISTS; i++)
1033  {
1034  List *list = buffer_lists[i];
1035  ListCell *cell;
1036 
1037  foreach(cell, list)
1038  {
1039  save_buffer *buf = (save_buffer *) lfirst(cell);
1040 
1041  if (buf->pid != 0)
1042  {
1043  StringInfo str = &(buf->data);
1044 
1045  write_syslogger_file(str->data, str->len,
1047  /* Mark the buffer unused, and reclaim string storage */
1048  buf->pid = 0;
1049  pfree(str->data);
1050  }
1051  }
1052  }
1053 
1054  /*
1055  * Force out any remaining pipe data as-is; we don't bother trying to
1056  * remove any protocol headers that may exist in it.
1057  */
1058  if (*bytes_in_logbuffer > 0)
1059  write_syslogger_file(logbuffer, *bytes_in_logbuffer,
1061  *bytes_in_logbuffer = 0;
1062 }
1063 
1064 
1065 /* --------------------------------
1066  * logfile routines
1067  * --------------------------------
1068  */
1069 
1070 /*
1071  * Write text to the currently open logfile
1072  *
1073  * This is exported so that elog.c can call it when MyBackendType is B_LOGGER.
1074  * This allows the syslogger process to record elog messages of its own,
1075  * even though its stderr does not point at the syslog pipe.
1076  */
1077 void
1078 write_syslogger_file(const char *buffer, int count, int destination)
1079 {
1080  int rc;
1081  FILE *logfile;
1082 
1083  /*
1084  * If we're told to write to csvlogFile, but it's not open, dump the data
1085  * to syslogFile (which is always open) instead. This can happen if CSV
1086  * output is enabled after postmaster start and we've been unable to open
1087  * csvlogFile. There are also race conditions during a parameter change
1088  * whereby backends might send us CSV output before we open csvlogFile or
1089  * after we close it. Writing CSV-formatted output to the regular log
1090  * file isn't great, but it beats dropping log output on the floor.
1091  *
1092  * Think not to improve this by trying to open csvlogFile on-the-fly. Any
1093  * failure in that would lead to recursion.
1094  */
1095  logfile = (destination == LOG_DESTINATION_CSVLOG &&
1096  csvlogFile != NULL) ? csvlogFile : syslogFile;
1097 
1098  rc = fwrite(buffer, 1, count, logfile);
1099 
1100  /*
1101  * Try to report any failure. We mustn't use ereport because it would
1102  * just recurse right back here, but write_stderr is OK: it will write
1103  * either to the postmaster's original stderr, or to /dev/null, but never
1104  * to our input pipe which would result in a different sort of looping.
1105  */
1106  if (rc != count)
1107  write_stderr("could not write to log file: %s\n", strerror(errno));
1108 }
1109 
1110 #ifdef WIN32
1111 
1112 /*
1113  * Worker thread to transfer data from the pipe to the current logfile.
1114  *
1115  * We need this because on Windows, WaitForMultipleObjects does not work on
1116  * unnamed pipes: it always reports "signaled", so the blocking ReadFile won't
1117  * allow for SIGHUP; and select is for sockets only.
1118  */
1119 static unsigned int __stdcall
1120 pipeThread(void *arg)
1121 {
1122  char logbuffer[READ_BUF_SIZE];
1123  int bytes_in_logbuffer = 0;
1124 
1125  for (;;)
1126  {
1127  DWORD bytesRead;
1128  BOOL result;
1129 
1130  result = ReadFile(syslogPipe[0],
1131  logbuffer + bytes_in_logbuffer,
1132  sizeof(logbuffer) - bytes_in_logbuffer,
1133  &bytesRead, 0);
1134 
1135  /*
1136  * Enter critical section before doing anything that might touch
1137  * global state shared by the main thread. Anything that uses
1138  * palloc()/pfree() in particular are not safe outside the critical
1139  * section.
1140  */
1141  EnterCriticalSection(&sysloggerSection);
1142  if (!result)
1143  {
1144  DWORD error = GetLastError();
1145 
1146  if (error == ERROR_HANDLE_EOF ||
1147  error == ERROR_BROKEN_PIPE)
1148  break;
1149  _dosmaperr(error);
1150  ereport(LOG,
1152  errmsg("could not read from logger pipe: %m")));
1153  }
1154  else if (bytesRead > 0)
1155  {
1156  bytes_in_logbuffer += bytesRead;
1157  process_pipe_input(logbuffer, &bytes_in_logbuffer);
1158  }
1159 
1160  /*
1161  * If we've filled the current logfile, nudge the main thread to do a
1162  * log rotation.
1163  */
1164  if (Log_RotationSize > 0)
1165  {
1166  if (ftell(syslogFile) >= Log_RotationSize * 1024L ||
1167  (csvlogFile != NULL && ftell(csvlogFile) >= Log_RotationSize * 1024L))
1168  SetLatch(MyLatch);
1169  }
1170  LeaveCriticalSection(&sysloggerSection);
1171  }
1172 
1173  /* We exit the above loop only upon detecting pipe EOF */
1174  pipe_eof_seen = true;
1175 
1176  /* if there's any data left then force it out now */
1177  flush_pipe_input(logbuffer, &bytes_in_logbuffer);
1178 
1179  /* set the latch to waken the main thread, which will quit */
1180  SetLatch(MyLatch);
1181 
1182  LeaveCriticalSection(&sysloggerSection);
1183  _endthread();
1184  return 0;
1185 }
1186 #endif /* WIN32 */
1187 
1188 /*
1189  * Open a new logfile with proper permissions and buffering options.
1190  *
1191  * If allow_errors is true, we just log any open failure and return NULL
1192  * (with errno still correct for the fopen failure).
1193  * Otherwise, errors are treated as fatal.
1194  */
1195 static FILE *
1196 logfile_open(const char *filename, const char *mode, bool allow_errors)
1197 {
1198  FILE *fh;
1199  mode_t oumask;
1200 
1201  /*
1202  * Note we do not let Log_file_mode disable IWUSR, since we certainly want
1203  * to be able to write the files ourselves.
1204  */
1205  oumask = umask((mode_t) ((~(Log_file_mode | S_IWUSR)) & (S_IRWXU | S_IRWXG | S_IRWXO)));
1206  fh = fopen(filename, mode);
1207  umask(oumask);
1208 
1209  if (fh)
1210  {
1211  setvbuf(fh, NULL, PG_IOLBF, 0);
1212 
1213 #ifdef WIN32
1214  /* use CRLF line endings on Windows */
1215  _setmode(_fileno(fh), _O_TEXT);
1216 #endif
1217  }
1218  else
1219  {
1220  int save_errno = errno;
1221 
1222  ereport(allow_errors ? LOG : FATAL,
1224  errmsg("could not open log file \"%s\": %m",
1225  filename)));
1226  errno = save_errno;
1227  }
1228 
1229  return fh;
1230 }
1231 
1232 /*
1233  * perform logfile rotation
1234  */
1235 static void
1236 logfile_rotate(bool time_based_rotation, int size_rotation_for)
1237 {
1238  char *filename;
1239  char *csvfilename = NULL;
1240  pg_time_t fntime;
1241  FILE *fh;
1242 
1243  rotation_requested = false;
1244 
1245  /*
1246  * When doing a time-based rotation, invent the new logfile name based on
1247  * the planned rotation time, not current time, to avoid "slippage" in the
1248  * file name when we don't do the rotation immediately.
1249  */
1250  if (time_based_rotation)
1251  fntime = next_rotation_time;
1252  else
1253  fntime = time(NULL);
1254  filename = logfile_getname(fntime, NULL);
1256  csvfilename = logfile_getname(fntime, ".csv");
1257 
1258  /*
1259  * Decide whether to overwrite or append. We can overwrite if (a)
1260  * Log_truncate_on_rotation is set, (b) the rotation was triggered by
1261  * elapsed time and not something else, and (c) the computed file name is
1262  * different from what we were previously logging into.
1263  *
1264  * Note: last_file_name should never be NULL here, but if it is, append.
1265  */
1266  if (time_based_rotation || (size_rotation_for & LOG_DESTINATION_STDERR))
1267  {
1268  if (Log_truncate_on_rotation && time_based_rotation &&
1269  last_file_name != NULL &&
1270  strcmp(filename, last_file_name) != 0)
1271  fh = logfile_open(filename, "w", true);
1272  else
1273  fh = logfile_open(filename, "a", true);
1274 
1275  if (!fh)
1276  {
1277  /*
1278  * ENFILE/EMFILE are not too surprising on a busy system; just
1279  * keep using the old file till we manage to get a new one.
1280  * Otherwise, assume something's wrong with Log_directory and stop
1281  * trying to create files.
1282  */
1283  if (errno != ENFILE && errno != EMFILE)
1284  {
1285  ereport(LOG,
1286  (errmsg("disabling automatic rotation (use SIGHUP to re-enable)")));
1287  rotation_disabled = true;
1288  }
1289 
1290  if (filename)
1291  pfree(filename);
1292  if (csvfilename)
1293  pfree(csvfilename);
1294  return;
1295  }
1296 
1297  fclose(syslogFile);
1298  syslogFile = fh;
1299 
1300  /* instead of pfree'ing filename, remember it for next time */
1301  if (last_file_name != NULL)
1304  filename = NULL;
1305  }
1306 
1307  /*
1308  * Same as above, but for csv file. Note that if LOG_DESTINATION_CSVLOG
1309  * was just turned on, we might have to open csvlogFile here though it was
1310  * not open before. In such a case we'll append not overwrite (since
1311  * last_csv_file_name will be NULL); that is consistent with the normal
1312  * rules since it's not a time-based rotation.
1313  */
1314  if ((Log_destination & LOG_DESTINATION_CSVLOG) &&
1315  (csvlogFile == NULL ||
1316  time_based_rotation || (size_rotation_for & LOG_DESTINATION_CSVLOG)))
1317  {
1318  if (Log_truncate_on_rotation && time_based_rotation &&
1319  last_csv_file_name != NULL &&
1320  strcmp(csvfilename, last_csv_file_name) != 0)
1321  fh = logfile_open(csvfilename, "w", true);
1322  else
1323  fh = logfile_open(csvfilename, "a", true);
1324 
1325  if (!fh)
1326  {
1327  /*
1328  * ENFILE/EMFILE are not too surprising on a busy system; just
1329  * keep using the old file till we manage to get a new one.
1330  * Otherwise, assume something's wrong with Log_directory and stop
1331  * trying to create files.
1332  */
1333  if (errno != ENFILE && errno != EMFILE)
1334  {
1335  ereport(LOG,
1336  (errmsg("disabling automatic rotation (use SIGHUP to re-enable)")));
1337  rotation_disabled = true;
1338  }
1339 
1340  if (filename)
1341  pfree(filename);
1342  if (csvfilename)
1343  pfree(csvfilename);
1344  return;
1345  }
1346 
1347  if (csvlogFile != NULL)
1348  fclose(csvlogFile);
1349  csvlogFile = fh;
1350 
1351  /* instead of pfree'ing filename, remember it for next time */
1352  if (last_csv_file_name != NULL)
1354  last_csv_file_name = csvfilename;
1355  csvfilename = NULL;
1356  }
1357  else if (!(Log_destination & LOG_DESTINATION_CSVLOG) &&
1358  csvlogFile != NULL)
1359  {
1360  /* CSVLOG was just turned off, so close the old file */
1361  fclose(csvlogFile);
1362  csvlogFile = NULL;
1363  if (last_csv_file_name != NULL)
1365  last_csv_file_name = NULL;
1366  }
1367 
1368  if (filename)
1369  pfree(filename);
1370  if (csvfilename)
1371  pfree(csvfilename);
1372 
1374 
1376 }
1377 
1378 
1379 /*
1380  * construct logfile name using timestamp information
1381  *
1382  * If suffix isn't NULL, append it to the name, replacing any ".log"
1383  * that may be in the pattern.
1384  *
1385  * Result is palloc'd.
1386  */
1387 static char *
1389 {
1390  char *filename;
1391  int len;
1392 
1393  filename = palloc(MAXPGPATH);
1394 
1395  snprintf(filename, MAXPGPATH, "%s/", Log_directory);
1396 
1397  len = strlen(filename);
1398 
1399  /* treat Log_filename as a strftime pattern */
1400  pg_strftime(filename + len, MAXPGPATH - len, Log_filename,
1401  pg_localtime(&timestamp, log_timezone));
1402 
1403  if (suffix != NULL)
1404  {
1405  len = strlen(filename);
1406  if (len > 4 && (strcmp(filename + (len - 4), ".log") == 0))
1407  len -= 4;
1408  strlcpy(filename + len, suffix, MAXPGPATH - len);
1409  }
1410 
1411  return filename;
1412 }
1413 
1414 /*
1415  * Determine the next planned rotation time, and store in next_rotation_time.
1416  */
1417 static void
1419 {
1420  pg_time_t now;
1421  struct pg_tm *tm;
1422  int rotinterval;
1423 
1424  /* nothing to do if time-based rotation is disabled */
1425  if (Log_RotationAge <= 0)
1426  return;
1427 
1428  /*
1429  * The requirements here are to choose the next time > now that is a
1430  * "multiple" of the log rotation interval. "Multiple" can be interpreted
1431  * fairly loosely. In this version we align to log_timezone rather than
1432  * GMT.
1433  */
1434  rotinterval = Log_RotationAge * SECS_PER_MINUTE; /* convert to seconds */
1435  now = (pg_time_t) time(NULL);
1436  tm = pg_localtime(&now, log_timezone);
1437  now += tm->tm_gmtoff;
1438  now -= now % rotinterval;
1439  now += rotinterval;
1440  now -= tm->tm_gmtoff;
1442 }
1443 
1444 /*
1445  * Store the name of the file(s) where the log collector, when enabled, writes
1446  * log messages. Useful for finding the name(s) of the current log file(s)
1447  * when there is time-based logfile rotation. Filenames are stored in a
1448  * temporary file and which is renamed into the final destination for
1449  * atomicity. The file is opened with the same permissions as what gets
1450  * created in the data directory and has proper buffering options.
1451  */
1452 static void
1454 {
1455  FILE *fh;
1456  mode_t oumask;
1457 
1460  {
1461  if (unlink(LOG_METAINFO_DATAFILE) < 0 && errno != ENOENT)
1462  ereport(LOG,
1464  errmsg("could not remove file \"%s\": %m",
1466  return;
1467  }
1468 
1469  /* use the same permissions as the data directory for the new file */
1470  oumask = umask(pg_mode_mask);
1471  fh = fopen(LOG_METAINFO_DATAFILE_TMP, "w");
1472  umask(oumask);
1473 
1474  if (fh)
1475  {
1476  setvbuf(fh, NULL, PG_IOLBF, 0);
1477 
1478 #ifdef WIN32
1479  /* use CRLF line endings on Windows */
1480  _setmode(_fileno(fh), _O_TEXT);
1481 #endif
1482  }
1483  else
1484  {
1485  ereport(LOG,
1487  errmsg("could not open file \"%s\": %m",
1489  return;
1490  }
1491 
1492  if (last_file_name && (Log_destination & LOG_DESTINATION_STDERR))
1493  {
1494  if (fprintf(fh, "stderr %s\n", last_file_name) < 0)
1495  {
1496  ereport(LOG,
1498  errmsg("could not write file \"%s\": %m",
1500  fclose(fh);
1501  return;
1502  }
1503  }
1504 
1505  if (last_csv_file_name && (Log_destination & LOG_DESTINATION_CSVLOG))
1506  {
1507  if (fprintf(fh, "csvlog %s\n", last_csv_file_name) < 0)
1508  {
1509  ereport(LOG,
1511  errmsg("could not write file \"%s\": %m",
1513  fclose(fh);
1514  return;
1515  }
1516  }
1517  fclose(fh);
1518 
1520  ereport(LOG,
1522  errmsg("could not rename file \"%s\" to \"%s\": %m",
1524 }
1525 
1526 /* --------------------------------
1527  * signal handler routines
1528  * --------------------------------
1529  */
1530 
1531 /*
1532  * Check to see if a log rotation request has arrived. Should be
1533  * called by postmaster after receiving SIGUSR1.
1534  */
1535 bool
1537 {
1538  struct stat stat_buf;
1539 
1540  if (stat(LOGROTATE_SIGNAL_FILE, &stat_buf) == 0)
1541  return true;
1542 
1543  return false;
1544 }
1545 
1546 /*
1547  * Remove the file signaling a log rotation request.
1548  */
1549 void
1551 {
1552  unlink(LOGROTATE_SIGNAL_FILE);
1553 }
1554 
1555 /* SIGUSR1: set flag to rotate logfile */
1556 static void
1558 {
1559  int save_errno = errno;
1560 
1561  rotation_requested = true;
1562  SetLatch(MyLatch);
1563 
1564  errno = save_errno;
1565 }
NON_EXEC_STATIC void SysLoggerMain(int argc, char *argv[]) pg_attribute_noreturn()
Definition: syslogger.c:156
#define PIPE_HEADER_SIZE
Definition: syslogger.h:60
size_t pg_strftime(char *s, size_t max, const char *format, const struct pg_tm *tm)
Definition: strftime.c:128
static void logfile_rotate(bool time_based_rotation, int size_rotation_for)
Definition: syslogger.c:1236
static PgChecksumMode mode
Definition: pg_checksums.c:61
#define pg_attribute_noreturn()
Definition: c.h:167
static pg_time_t next_rotation_time
Definition: syslogger.c:83
#define SIGQUIT
Definition: win32_port.h:160
void write_syslogger_file(const char *buffer, int count, int destination)
Definition: syslogger.c:1078
int32 pid
Definition: syslogger.c:105
char nuls[2]
Definition: syslogger.h:46
#define DEBUG1
Definition: elog.h:25
int errhint(const char *fmt,...)
Definition: elog.c:1149
int64 pg_time_t
Definition: pgtime.h:23
char * Log_directory
Definition: syslogger.c:73
void ProcessConfigFile(GucContext context)
static void error(void)
Definition: sql-dyntest.c:147
int AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, Latch *latch, void *user_data)
Definition: latch.c:808
void InitPostmasterChild(void)
Definition: miscinit.c:93
#define SIGUSR1
Definition: win32_port.h:171
BackendType MyBackendType
Definition: miscinit.c:62
int64 timestamp
#define SIGCHLD
Definition: win32_port.h:169
pid_t fork_process(void)
Definition: fork_process.c:29
#define READ_BUF_SIZE
Definition: syslogger.c:60
void SignalHandlerForConfigReload(SIGNAL_ARGS)
Definition: interrupt.c:56
char * pstrdup(const char *in)
Definition: mcxt.c:1187
static FILE * csvlogFile
Definition: syslogger.c:87
#define PIPE_MAX_PAYLOAD
Definition: syslogger.h:61
pg_time_t MyStartTime
Definition: globals.c:41
#define write_stderr(str)
Definition: parallel.c:186
void _dosmaperr(unsigned long)
Definition: win32error.c:171
void proc_exit(int code)
Definition: ipc.c:104
#define LOG_METAINFO_DATAFILE
Definition: syslogger.h:95
#define WL_SOCKET_READABLE
Definition: latch.h:125
static FILE * logfile
Definition: pg_regress.c:102
int SysLogger_Start(void)
Definition: syslogger.c:539
#define lengthof(array)
Definition: c.h:730
#define SIGPIPE
Definition: win32_port.h:164
long int tm_gmtoff
Definition: pgtime.h:36
Definition: pgtime.h:25
#define SIGUSR2
Definition: win32_port.h:172
static void set_next_rotation_time(void)
Definition: syslogger.c:1418
#define LOG
Definition: elog.h:26
void SetLatch(Latch *latch)
Definition: latch.c:505
#define fprintf
Definition: port.h:219
void ClosePostmasterPorts(bool am_syslogger)
Definition: postmaster.c:2568
static int fd(const char *x, int i)
Definition: preproc-init.c:105
void PGSharedMemoryDetach(void)
Definition: sysv_shmem.c:909
void ResetLatch(Latch *latch)
Definition: latch.c:588
#define PG_SETMASK(mask)
Definition: pqsignal.h:19
#define MINS_PER_HOUR
Definition: timestamp.h:89
signed int int32
Definition: c.h:417
bool Logging_collector
Definition: syslogger.c:70
static struct pg_tm tm
Definition: localtime.c:102
pg_tz * log_timezone
Definition: pgtz.c:31
int Log_RotationSize
Definition: syslogger.c:72
bool redirection_done
Definition: postmaster.c:364
WaitEventSet * CreateWaitEventSet(MemoryContext context, int nevents)
Definition: latch.c:611
int Log_file_mode
Definition: syslogger.c:76
static char * last_file_name
Definition: syslogger.c:89
void pfree(void *pointer)
Definition: mcxt.c:1057
#define NBUFFER_LISTS
Definition: syslogger.c:109
#define S_IWUSR
Definition: win32_port.h:283
#define FATAL
Definition: elog.h:52
uint32 events
Definition: latch.h:144
#define MAXPGPATH
static void sigUsr1Handler(SIGNAL_ARGS)
Definition: syslogger.c:1557
static char * logfile_getname(pg_time_t timestamp, const char *suffix)
Definition: syslogger.c:1388
static void process_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
Definition: syslogger.c:876
Definition: dest.h:89
static bool rotation_disabled
Definition: syslogger.c:85
static char * buf
Definition: pg_test_fsync.c:68
#define HOURS_PER_DAY
Definition: timestamp.h:78
#define SECS_PER_MINUTE
Definition: timestamp.h:88
#define S_IRWXG
Definition: win32_port.h:301
int errcode_for_file_access(void)
Definition: elog.c:714
#define SIGHUP
Definition: win32_port.h:159
Definition: type.h:130
sigset_t UnBlockSig
Definition: pqsignal.c:22
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
#define DEVNULL
Definition: port.h:146
static char * last_csv_file_name
Definition: syslogger.c:90
int errcode_for_socket_access(void)
Definition: elog.c:785
Definition: guc.h:72
static List * buffer_lists[NBUFFER_LISTS]
Definition: syslogger.c:110
List * lappend(List *list, void *datum)
Definition: list.c:321
StringInfoData data
Definition: syslogger.c:106
#define SIG_IGN
Definition: win32_port.h:156
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
bool CheckLogrotateSignal(void)
Definition: syslogger.c:1536
struct @17::@18 av[32]
#define PGINVALID_SOCKET
Definition: port.h:33
void RemoveLogrotateSignalFiles(void)
Definition: syslogger.c:1550
#define PG_IOLBF
Definition: port.h:343
#define LOG_DESTINATION_CSVLOG
Definition: elog.h:435
#define LOG_DESTINATION_STDERR
Definition: elog.h:432
#define ereport(elevel,...)
Definition: elog.h:155
int MakePGDirectory(const char *directoryName)
Definition: fd.c:3611
int Log_RotationAge
Definition: syslogger.c:71
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:170
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define SIG_DFL
Definition: win32_port.h:154
#define SIGNAL_ARGS
Definition: c.h:1329
#define Assert(condition)
Definition: c.h:800
#define lfirst(lc)
Definition: pg_list.h:169
#define strerror
Definition: port.h:228
#define SIGALRM
Definition: win32_port.h:165
NON_EXEC_STATIC pg_time_t first_syslogger_file_time
Definition: syslogger.c:88
static void update_metainfo_datafile(void)
Definition: syslogger.c:1453
#define LOG_METAINFO_DATAFILE_TMP
Definition: syslogger.h:96
void dsm_detach_all(void)
Definition: dsm.c:741
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
Definition: localtime.c:1342
static FILE * syslogFile
Definition: syslogger.c:86
#define S_IRUSR
Definition: win32_port.h:280
char * Log_filename
Definition: syslogger.c:74
static bool pipe_eof_seen
Definition: syslogger.c:84
static void flush_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
Definition: syslogger.c:1027
static char * filename
Definition: pg_dumpall.c:91
#define S_IRWXU
Definition: win32_port.h:289
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:902
static FILE * logfile_open(const char *filename, const char *mode, bool allow_errors)
Definition: syslogger.c:1196
#define elog(elevel,...)
Definition: elog.h:228
bool Log_truncate_on_rotation
Definition: syslogger.c:75
volatile sig_atomic_t ConfigReloadPending
Definition: interrupt.c:26
int i
#define LOGROTATE_SIGNAL_FILE
Definition: syslogger.c:63
void * arg
struct Latch * MyLatch
Definition: globals.c:54
int Log_destination
Definition: elog.c:110
void init_ps_display(const char *fixed_part)
Definition: ps_status.c:258
#define close(a)
Definition: win32.h:12
#define EINTR
Definition: win32_port.h:343
CommandDest whereToSendOutput
Definition: postgres.c:91
static volatile sig_atomic_t rotation_requested
Definition: syslogger.c:127
Definition: pg_list.h:50
#define snprintf
Definition: port.h:215
#define WL_LATCH_SET
Definition: latch.h:124
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227
int pg_mode_mask
Definition: file_perm.c:25
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1542
#define read(a, b, c)
Definition: win32.h:13
#define offsetof(type, field)
Definition: c.h:723
#define S_IRWXO
Definition: win32_port.h:313
#define stat
Definition: win32_port.h:275
int WaitEventSetWait(WaitEventSet *set, long timeout, WaitEvent *occurred_events, int nevents, uint32 wait_event_info)
Definition: latch.c:1231
#define NON_EXEC_STATIC
Definition: c.h:1347
int syslogPipe[2]
Definition: syslogger.c:114