1 /*-------------------------------------------------------------------------
5 * The system logger (syslogger) is new 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 an internal naming scheme that mangles
13 * creation time and current postmaster pid.
15 * Author: Andreas Pflug <pgadmin@pse-consulting.de>
17 * Copyright (c) 2004-2007, PostgreSQL Global Development Group
21 * $PostgreSQL: pgsql/src/backend/postmaster/syslogger.c,v 1.41 2007/11/15 21:14:37 momjian Exp $
23 *-------------------------------------------------------------------------
34 #include "lib/stringinfo.h"
35 #include "libpq/pqsignal.h"
36 #include "miscadmin.h"
38 #include "postmaster/fork_process.h"
39 #include "postmaster/postmaster.h"
40 #include "postmaster/syslogger.h"
41 #include "storage/ipc.h"
42 #include "storage/pg_shmem.h"
43 #include "utils/guc.h"
44 #include "utils/ps_status.h"
45 #include "utils/timestamp.h"
48 * We really want line-buffered mode for logfile output, but Windows does
49 * not have it, and interprets _IOLBF as _IOFBF (bozos). So use _IONBF
53 #define LBF_MODE _IONBF
55 #define LBF_MODE _IOLBF
59 * We read() into a temp buffer twice as big as a chunk, so that any fragment
60 * left after processing can be moved down to the front and we'll still have
61 * room to read a full chunk.
63 #define READ_BUF_SIZE (2 * PIPE_CHUNK_SIZE)
67 * GUC parameters. Logging_collector cannot be changed after postmaster
68 * start, but the rest can change at SIGHUP.
70 bool Logging_collector = false;
71 int Log_RotationAge = HOURS_PER_DAY * MINS_PER_HOUR;
72 int Log_RotationSize = 10 * 1024;
73 char *Log_directory = NULL;
74 char *Log_filename = NULL;
75 bool Log_truncate_on_rotation = false;
78 * Globally visible state (used by elog.c)
80 bool am_syslogger = false;
82 extern bool redirection_done;
87 static pg_time_t next_rotation_time;
88 static bool pipe_eof_seen = false;
89 static FILE *syslogFile = NULL;
90 static FILE *csvlogFile = NULL;
91 static char *last_file_name = NULL;
92 static char *last_csvfile_name = NULL;
95 * Buffers for saving partial messages from different backends. We don't expect
96 * that there will be very many outstanding at one time, so 20 seems plenty of
97 * leeway. If this array gets full we won't lose messages, but we will lose
98 * the protocol protection against them being partially written or interleaved.
100 * An inactive buffer has pid == 0 and undefined contents of data.
104 int32 pid; /* PID of source process */
105 StringInfoData data; /* accumulated data, as a StringInfo */
108 #define CHUNK_SLOTS 20
109 static save_buffer saved_chunks[CHUNK_SLOTS];
111 /* These must be exported for EXEC_BACKEND case ... annoying */
113 int syslogPipe[2] = {-1, -1};
115 HANDLE syslogPipe[2] = {0, 0};
119 static HANDLE threadHandle = 0;
120 static CRITICAL_SECTION sysfileSection;
124 * Flags set by interrupt handlers for later service in the main loop.
126 static volatile sig_atomic_t got_SIGHUP = false;
127 static volatile sig_atomic_t rotation_requested = false;
130 /* Local subroutines */
132 static pid_t syslogger_forkexec(void);
133 static void syslogger_parseArgs(int argc, char *argv[]);
135 static void process_pipe_input(char *logbuffer, int *bytes_in_logbuffer);
136 static void flush_pipe_input(char *logbuffer, int *bytes_in_logbuffer);
137 static void open_csvlogfile(void);
140 static unsigned int __stdcall pipeThread(void *arg);
142 static void logfile_rotate(bool time_based_rotation, int size_rotation_for);
143 static char *logfile_getname(pg_time_t timestamp, char *suffix);
144 static void set_next_rotation_time(void);
145 static void sigHupHandler(SIGNAL_ARGS);
146 static void sigUsr1Handler(SIGNAL_ARGS);
150 * Main entry point for syslogger process
151 * argc/argv parameters are valid only in EXEC_BACKEND case.
154 SysLoggerMain(int argc, char *argv[])
157 char logbuffer[READ_BUF_SIZE];
158 int bytes_in_logbuffer = 0;
161 char *currentLogFilename;
162 int currentLogRotationAge;
164 IsUnderPostmaster = true; /* we are a postmaster subprocess now */
166 MyProcPid = getpid(); /* reset MyProcPid */
168 MyStartTime = time(NULL); /* set our start time in case we call elog */
171 syslogger_parseArgs(argc, argv);
172 #endif /* EXEC_BACKEND */
176 init_ps_display("logger process", "", "", "");
179 * If we restarted, our stderr is already redirected into our own input
180 * pipe. This is of course pretty useless, not to mention that it
181 * interferes with detecting pipe EOF. Point stderr to /dev/null. This
182 * assumes that all interesting messages generated in the syslogger will
183 * come through elog.c and will be sent to write_syslogger_file.
185 if (redirection_done)
187 int fd = open(NULL_DEV, O_WRONLY, 0);
190 * The closes might look redundant, but they are not: we want to be
191 * darn sure the pipe gets closed even if the open failed. We can
192 * survive running with stderr pointing nowhere, but we can't afford
193 * to have extra pipe input descriptors hanging around.
195 close(fileno(stdout));
196 close(fileno(stderr));
197 dup2(fd, fileno(stdout));
198 dup2(fd, fileno(stderr));
203 * Syslogger's own stderr can't be the syslogPipe, so set it back to text
204 * mode if we didn't just close it. (It was set to binary in
205 * SubPostmasterMain).
209 _setmode(_fileno(stderr), _O_TEXT);
213 * Also close our copy of the write end of the pipe. This is needed to
214 * ensure we can detect pipe EOF correctly. (But note that in the restart
215 * case, the postmaster already did this.)
218 if (syslogPipe[1] >= 0)
219 close(syslogPipe[1]);
223 CloseHandle(syslogPipe[1]);
228 * If possible, make this process a group leader, so that the postmaster
229 * can signal any child processes too. (syslogger probably never has any
230 * child processes, but for consistency we make all postmaster child
231 * processes do this.)
235 elog(FATAL, "setsid() failed: %m");
239 * Properly accept or ignore signals the postmaster might send us
241 * Note: we ignore all termination signals, and instead exit only when all
242 * upstream processes are gone, to ensure we don't miss any dying gasps of
246 pqsignal(SIGHUP, sigHupHandler); /* set flag to read config file */
247 pqsignal(SIGINT, SIG_IGN);
248 pqsignal(SIGTERM, SIG_IGN);
249 pqsignal(SIGQUIT, SIG_IGN);
250 pqsignal(SIGALRM, SIG_IGN);
251 pqsignal(SIGPIPE, SIG_IGN);
252 pqsignal(SIGUSR1, sigUsr1Handler); /* request log rotation */
253 pqsignal(SIGUSR2, SIG_IGN);
256 * Reset some signals that are accepted by postmaster but not here
258 pqsignal(SIGCHLD, SIG_DFL);
259 pqsignal(SIGTTIN, SIG_DFL);
260 pqsignal(SIGTTOU, SIG_DFL);
261 pqsignal(SIGCONT, SIG_DFL);
262 pqsignal(SIGWINCH, SIG_DFL);
264 PG_SETMASK(&UnBlockSig);
267 /* Fire up separate data transfer thread */
268 InitializeCriticalSection(&sysfileSection);
273 threadHandle = (HANDLE) _beginthreadex(0, 0, pipeThread, 0, 0, &tid);
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 */
282 set_next_rotation_time();
284 /* main worker loop */
287 bool time_based_rotation = false;
288 int size_rotation_for = 0;
294 struct timeval timeout;
300 ProcessConfigFile(PGC_SIGHUP);
303 * Check if the log directory or filename pattern changed in
304 * postgresql.conf. If so, force rotation to make sure we're
305 * writing the logfiles in the right place.
307 if (strcmp(Log_directory, currentLogDir) != 0)
309 pfree(currentLogDir);
310 currentLogDir = pstrdup(Log_directory);
311 rotation_requested = true;
313 if (strcmp(Log_filename, currentLogFilename) != 0)
315 pfree(currentLogFilename);
316 currentLogFilename = pstrdup(Log_filename);
317 rotation_requested = true;
321 * If rotation time parameter changed, reset next rotation time,
322 * but don't immediately force a rotation.
324 if (currentLogRotationAge != Log_RotationAge)
326 currentLogRotationAge = Log_RotationAge;
327 set_next_rotation_time();
331 if (!rotation_requested && Log_RotationAge > 0)
333 /* Do a logfile rotation if it's time */
334 pg_time_t now = time(NULL);
336 if (now >= next_rotation_time)
337 rotation_requested = time_based_rotation = true;
340 if (!rotation_requested && Log_RotationSize > 0)
342 /* Do a rotation if file is too big */
343 if (ftell(syslogFile) >= Log_RotationSize * 1024L)
345 rotation_requested = true;
346 size_rotation_for |= LOG_DESTINATION_STDERR;
348 if (csvlogFile != NULL && ftell(csvlogFile) >= Log_RotationSize * 1024L)
350 rotation_requested = true;
351 size_rotation_for |= LOG_DESTINATION_CSVLOG;
356 if (rotation_requested)
359 * Force rotation when both values are zero. It means the request
360 * was sent by pg_rotate_logfile.
362 if (!time_based_rotation && size_rotation_for == 0)
363 size_rotation_for = LOG_DESTINATION_STDERR | LOG_DESTINATION_CSVLOG;
364 logfile_rotate(time_based_rotation, size_rotation_for);
370 * Wait for some data, timing out after 1 second
373 FD_SET(syslogPipe[0], &rfds);
377 rc = select(syslogPipe[0] + 1, &rfds, NULL, NULL, &timeout);
383 (errcode_for_socket_access(),
384 errmsg("select() failed in logger process: %m")));
386 else if (rc > 0 && FD_ISSET(syslogPipe[0], &rfds))
388 bytesRead = piperead(syslogPipe[0],
389 logbuffer + bytes_in_logbuffer,
390 sizeof(logbuffer) - bytes_in_logbuffer);
395 (errcode_for_socket_access(),
396 errmsg("could not read from logger pipe: %m")));
398 else if (bytesRead > 0)
400 bytes_in_logbuffer += bytesRead;
401 process_pipe_input(logbuffer, &bytes_in_logbuffer);
407 * Zero bytes read when select() is saying read-ready means
408 * EOF on the pipe: that is, there are no longer any processes
409 * with the pipe write end open. Therefore, the postmaster
410 * and all backends are shut down, and we are done.
412 pipe_eof_seen = true;
414 /* if there's any data left then force it out now */
415 flush_pipe_input(logbuffer, &bytes_in_logbuffer);
421 * On Windows we leave it to a separate thread to transfer data and
422 * detect pipe EOF. The main thread just wakes up once a second to
423 * check for SIGHUP and rotation conditions.
431 * seeing this message on the real stderr is annoying - so we make
432 * it DEBUG1 to suppress in normal use.
435 (errmsg("logger shutting down")));
438 * Normal exit from the syslogger is here. Note that we
439 * deliberately do not close syslogFile before exiting; this is to
440 * allow for the possibility of elog messages being generated
441 * inside proc_exit. Regular exit() will take care of flushing
442 * and closing stdio channels.
450 * Postmaster subroutine to start a syslogger subprocess.
453 SysLogger_Start(void)
458 if (!Logging_collector)
462 * If first time through, create the pipe which will receive stderr
465 * If the syslogger crashes and needs to be restarted, we continue to use
466 * the same pipe (indeed must do so, since extant backends will be writing
469 * This means the postmaster must continue to hold the read end of the
470 * pipe open, so we can pass it down to the reincarnated syslogger. This
471 * is a bit klugy but we have little choice.
474 if (syslogPipe[0] < 0)
476 if (pgpipe(syslogPipe) < 0)
478 (errcode_for_socket_access(),
479 (errmsg("could not create pipe for syslog: %m"))));
484 SECURITY_ATTRIBUTES sa;
486 memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
487 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
488 sa.bInheritHandle = TRUE;
490 if (!CreatePipe(&syslogPipe[0], &syslogPipe[1], &sa, 32768))
492 (errcode_for_file_access(),
493 (errmsg("could not create pipe for syslog: %m"))));
498 * Create log directory if not present; ignore errors
500 mkdir(Log_directory, 0700);
503 * The initial logfile is created right in the postmaster, to verify that
504 * the Log_directory is writable.
506 filename = logfile_getname(time(NULL), NULL);
508 syslogFile = fopen(filename, "a");
512 (errcode_for_file_access(),
513 (errmsg("could not create log file \"%s\": %m",
516 setvbuf(syslogFile, NULL, LBF_MODE, 0);
521 switch ((sysloggerPid = syslogger_forkexec()))
523 switch ((sysloggerPid = fork_process()))
528 (errmsg("could not fork system logger: %m")));
533 /* in postmaster child ... */
534 /* Close the postmaster's sockets */
535 ClosePostmasterPorts(true);
537 /* Lose the postmaster's on-exit routines */
540 /* Drop our connection to postmaster's shared memory, as well */
541 PGSharedMemoryDetach();
544 SysLoggerMain(0, NULL);
549 /* success, in postmaster */
551 /* now we redirect stderr, if not done already */
552 if (!redirection_done)
556 if (dup2(syslogPipe[1], fileno(stdout)) < 0)
558 (errcode_for_file_access(),
559 errmsg("could not redirect stdout: %m")));
561 if (dup2(syslogPipe[1], fileno(stderr)) < 0)
563 (errcode_for_file_access(),
564 errmsg("could not redirect stderr: %m")));
565 /* Now we are done with the write end of the pipe. */
566 close(syslogPipe[1]);
572 * open the pipe in binary mode and make sure stderr is binary
573 * after it's been dup'ed into, to avoid disturbing the pipe
577 fd = _open_osfhandle((long) syslogPipe[1],
578 _O_APPEND | _O_BINARY);
579 if (dup2(fd, _fileno(stderr)) < 0)
581 (errcode_for_file_access(),
582 errmsg("could not redirect stderr: %m")));
584 _setmode(_fileno(stderr), _O_BINARY);
585 /* Now we are done with the write end of the pipe. */
586 CloseHandle(syslogPipe[1]);
589 redirection_done = true;
592 /* postmaster will never write the file; close it */
595 return (int) sysloggerPid;
598 /* we should never reach here */
606 * syslogger_forkexec() -
608 * Format up the arglist for, then fork and exec, a syslogger process
611 syslogger_forkexec(void)
617 av[ac++] = "postgres";
618 av[ac++] = "--forklog";
619 av[ac++] = NULL; /* filled in by postmaster_forkexec */
621 /* static variables (those not passed by write_backend_variables) */
623 if (syslogFile != NULL)
624 snprintf(filenobuf, sizeof(filenobuf), "%d",
627 strcpy(filenobuf, "-1");
629 if (syslogFile != NULL)
630 snprintf(filenobuf, sizeof(filenobuf), "%ld",
631 _get_osfhandle(_fileno(syslogFile)));
633 strcpy(filenobuf, "0");
635 av[ac++] = filenobuf;
638 Assert(ac < lengthof(av));
640 return postmaster_forkexec(ac, av);
644 * syslogger_parseArgs() -
646 * Extract data from the arglist for exec'ed syslogger process
649 syslogger_parseArgs(int argc, char *argv[])
660 syslogFile = fdopen(fd, "a");
661 setvbuf(syslogFile, NULL, LBF_MODE, 0);
667 fd = _open_osfhandle(fd, _O_APPEND | _O_TEXT);
670 syslogFile = fdopen(fd, "a");
671 setvbuf(syslogFile, NULL, LBF_MODE, 0);
676 #endif /* EXEC_BACKEND */
679 /* --------------------------------
680 * pipe protocol handling
681 * --------------------------------
685 * Process data received through the syslogger pipe.
687 * This routine interprets the log pipe protocol which sends log messages as
688 * (hopefully atomic) chunks - such chunks are detected and reassembled here.
690 * The protocol has a header that starts with two nul bytes, then has a 16 bit
691 * length, the pid of the sending process, and a flag to indicate if it is
692 * the last chunk in a message. Incomplete chunks are saved until we read some
693 * more, and non-final chunks are accumulated until we get the final chunk.
695 * All of this is to avoid 2 problems:
696 * . partial messages being written to logfiles (messes rotation), and
697 * . messages from different backends being interleaved (messages garbled).
699 * Any non-protocol messages are written out directly. These should only come
700 * from non-PostgreSQL sources, however (e.g. third party libraries writing to
703 * logbuffer is the data input buffer, and *bytes_in_logbuffer is the number
704 * of bytes present. On exit, any not-yet-eaten data is left-justified in
705 * logbuffer, and *bytes_in_logbuffer is updated.
708 process_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
710 char *cursor = logbuffer;
711 int count = *bytes_in_logbuffer;
712 int dest = LOG_DESTINATION_STDERR;
714 /* While we have enough for a header, process data... */
715 while (count >= (int) sizeof(PipeProtoHeader))
720 /* Do we have a valid header? */
721 memcpy(&p, cursor, sizeof(PipeProtoHeader));
722 if (p.nuls[0] == '\0' && p.nuls[1] == '\0' &&
723 p.len > 0 && p.len <= PIPE_MAX_PAYLOAD &&
725 (p.is_last == 't' || p.is_last == 'f' ||
726 p.is_last == 'T' || p.is_last == 'F'))
728 chunklen = PIPE_HEADER_SIZE + p.len;
730 /* Fall out of loop if we don't have the whole chunk yet */
731 if (count < chunklen)
734 dest = (p.is_last == 'T' || p.is_last == 'F') ?
735 LOG_DESTINATION_CSVLOG : LOG_DESTINATION_STDERR;
737 if (p.is_last == 'f' || p.is_last == 'F')
740 * Save a complete non-final chunk in the per-pid buffer if
741 * possible - if not just write it out.
748 for (i = 0; i < CHUNK_SLOTS; i++)
750 if (saved_chunks[i].pid == p.pid)
755 if (free_slot < 0 && saved_chunks[i].pid == 0)
758 if (existing_slot >= 0)
760 str = &(saved_chunks[existing_slot].data);
761 appendBinaryStringInfo(str,
762 cursor + PIPE_HEADER_SIZE,
765 else if (free_slot >= 0)
767 saved_chunks[free_slot].pid = p.pid;
768 str = &(saved_chunks[free_slot].data);
770 appendBinaryStringInfo(str,
771 cursor + PIPE_HEADER_SIZE,
777 * If there is no free slot we'll just have to take our
778 * chances and write out a partial message and hope that
779 * it's not followed by something from another pid.
781 write_syslogger_file(cursor + PIPE_HEADER_SIZE, p.len,
788 * Final chunk --- add it to anything saved for that pid, and
789 * either way write the whole thing out.
791 int existing_slot = -1;
795 for (i = 0; i < CHUNK_SLOTS; i++)
797 if (saved_chunks[i].pid == p.pid)
803 if (existing_slot >= 0)
805 str = &(saved_chunks[existing_slot].data);
806 appendBinaryStringInfo(str,
807 cursor + PIPE_HEADER_SIZE,
809 write_syslogger_file(str->data, str->len, dest);
810 saved_chunks[existing_slot].pid = 0;
815 /* The whole message was one chunk, evidently. */
816 write_syslogger_file(cursor + PIPE_HEADER_SIZE, p.len,
821 /* Finished processing this chunk */
827 /* Process non-protocol data */
830 * Look for the start of a protocol header. If found, dump data
831 * up to there and repeat the loop. Otherwise, dump it all and
832 * fall out of the loop. (Note: we want to dump it all if at all
833 * possible, so as to avoid dividing non-protocol messages across
834 * logfiles. We expect that in many scenarios, a non-protocol
835 * message will arrive all in one read(), and we want to respect
836 * the read() boundary if possible.)
838 for (chunklen = 1; chunklen < count; chunklen++)
840 if (cursor[chunklen] == '\0')
843 /* fall back on the stderr log as the destination */
844 write_syslogger_file(cursor, chunklen, LOG_DESTINATION_STDERR);
850 /* We don't have a full chunk, so left-align what remains in the buffer */
851 if (count > 0 && cursor != logbuffer)
852 memmove(logbuffer, cursor, count);
853 *bytes_in_logbuffer = count;
857 * Force out any buffered data
859 * This is currently used only at syslogger shutdown, but could perhaps be
860 * useful at other times, so it is careful to leave things in a clean state.
863 flush_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
868 /* Dump any incomplete protocol messages */
869 for (i = 0; i < CHUNK_SLOTS; i++)
871 if (saved_chunks[i].pid != 0)
873 str = &(saved_chunks[i].data);
874 write_syslogger_file(str->data, str->len, LOG_DESTINATION_STDERR);
875 saved_chunks[i].pid = 0;
881 * Force out any remaining pipe data as-is; we don't bother trying to
882 * remove any protocol headers that may exist in it.
884 if (*bytes_in_logbuffer > 0)
885 write_syslogger_file(logbuffer, *bytes_in_logbuffer,
886 LOG_DESTINATION_STDERR);
887 *bytes_in_logbuffer = 0;
891 /* --------------------------------
893 * --------------------------------
897 * Write text to the currently open logfile
899 * This is exported so that elog.c can call it when am_syslogger is true.
900 * This allows the syslogger process to record elog messages of its own,
901 * even though its stderr does not point at the syslog pipe.
904 write_syslogger_file(const char *buffer, int count, int destination)
909 if (destination == LOG_DESTINATION_CSVLOG && csvlogFile == NULL)
912 logfile = destination == LOG_DESTINATION_CSVLOG ? csvlogFile : syslogFile;
915 rc = fwrite(buffer, 1, count, logfile);
917 EnterCriticalSection(&sysfileSection);
918 rc = fwrite(buffer, 1, count, logfile);
919 LeaveCriticalSection(&sysfileSection);
922 /* can't use ereport here because of possible recursion */
924 write_stderr("could not write to log file: %s\n", strerror(errno));
930 * Worker thread to transfer data from the pipe to the current logfile.
932 * We need this because on Windows, WaitForSingleObject does not work on
933 * unnamed pipes: it always reports "signaled", so the blocking ReadFile won't
934 * allow for SIGHUP; and select is for sockets only.
936 static unsigned int __stdcall
937 pipeThread(void *arg)
939 char logbuffer[READ_BUF_SIZE];
940 int bytes_in_logbuffer = 0;
946 if (!ReadFile(syslogPipe[0],
947 logbuffer + bytes_in_logbuffer,
948 sizeof(logbuffer) - bytes_in_logbuffer,
951 DWORD error = GetLastError();
953 if (error == ERROR_HANDLE_EOF ||
954 error == ERROR_BROKEN_PIPE)
958 (errcode_for_file_access(),
959 errmsg("could not read from logger pipe: %m")));
961 else if (bytesRead > 0)
963 bytes_in_logbuffer += bytesRead;
964 process_pipe_input(logbuffer, &bytes_in_logbuffer);
968 /* We exit the above loop only upon detecting pipe EOF */
969 pipe_eof_seen = true;
971 /* if there's any data left then force it out now */
972 flush_pipe_input(logbuffer, &bytes_in_logbuffer);
980 * open the csv log file - we do this opportunistically, because
981 * we don't know if CSV logging will be wanted.
984 open_csvlogfile(void)
989 filename = logfile_getname(time(NULL), ".csv");
991 fh = fopen(filename, "a");
995 (errcode_for_file_access(),
996 (errmsg("could not create log file \"%s\": %m",
999 setvbuf(fh, NULL, LBF_MODE, 0);
1002 _setmode(_fileno(fh), _O_TEXT); /* use CRLF line endings on Windows */
1012 * perform logfile rotation
1015 logfile_rotate(bool time_based_rotation, int size_rotation_for)
1018 char *csvfilename = NULL;
1021 rotation_requested = false;
1024 * When doing a time-based rotation, invent the new logfile name based on
1025 * the planned rotation time, not current time, to avoid "slippage" in the
1026 * file name when we don't do the rotation immediately.
1028 if (time_based_rotation)
1030 filename = logfile_getname(next_rotation_time, NULL);
1031 if (csvlogFile != NULL)
1032 csvfilename = logfile_getname(next_rotation_time, ".csv");
1036 filename = logfile_getname(time(NULL), NULL);
1037 if (csvlogFile != NULL)
1038 csvfilename = logfile_getname(time(NULL), ".csv");
1042 * Decide whether to overwrite or append. We can overwrite if (a)
1043 * Log_truncate_on_rotation is set, (b) the rotation was triggered by
1044 * elapsed time and not something else, and (c) the computed file name is
1045 * different from what we were previously logging into.
1047 * Note: during the first rotation after forking off from the postmaster,
1048 * last_file_name will be NULL. (We don't bother to set it in the
1049 * postmaster because it ain't gonna work in the EXEC_BACKEND case.) So we
1050 * will always append in that situation, even though truncating would
1053 * For consistency, we treat CSV logs the same even though they aren't
1054 * opened in the postmaster.
1056 if (time_based_rotation || (size_rotation_for & LOG_DESTINATION_STDERR))
1058 if (Log_truncate_on_rotation && time_based_rotation &&
1059 last_file_name != NULL && strcmp(filename, last_file_name) != 0)
1060 fh = fopen(filename, "w");
1062 fh = fopen(filename, "a");
1066 int saveerrno = errno;
1069 (errcode_for_file_access(),
1070 errmsg("could not open new log file \"%s\": %m",
1074 * ENFILE/EMFILE are not too surprising on a busy system; just
1075 * keep using the old file till we manage to get a new one.
1076 * Otherwise, assume something's wrong with Log_directory and stop
1077 * trying to create files.
1079 if (saveerrno != ENFILE && saveerrno != EMFILE)
1082 (errmsg("disabling automatic rotation (use SIGHUP to reenable)")));
1083 Log_RotationAge = 0;
1084 Log_RotationSize = 0;
1090 setvbuf(fh, NULL, LBF_MODE, 0);
1093 _setmode(_fileno(fh), _O_TEXT); /* use CRLF line endings on Windows */
1096 /* On Windows, need to interlock against data-transfer thread */
1098 EnterCriticalSection(&sysfileSection);
1103 LeaveCriticalSection(&sysfileSection);
1106 /* instead of pfree'ing filename, remember it for next time */
1107 if (last_file_name != NULL)
1108 pfree(last_file_name);
1109 last_file_name = filename;
1114 /* same as above, but for csv file. */
1116 if (csvlogFile != NULL && (
1117 time_based_rotation ||
1118 (size_rotation_for & LOG_DESTINATION_STDERR)))
1120 if (Log_truncate_on_rotation && time_based_rotation &&
1121 last_csvfile_name != NULL &&
1122 strcmp(csvfilename, last_csvfile_name) != 0)
1124 fh = fopen(csvfilename, "w");
1126 fh = fopen(csvfilename, "a");
1130 int saveerrno = errno;
1133 (errcode_for_file_access(),
1134 errmsg("could not open new log file \"%s\": %m",
1138 * ENFILE/EMFILE are not too surprising on a busy system; just
1139 * keep using the old file till we manage to get a new one.
1140 * Otherwise, assume something's wrong with Log_directory and stop
1141 * trying to create files.
1143 if (saveerrno != ENFILE && saveerrno != EMFILE)
1146 (errmsg("disabling automatic rotation (use SIGHUP to reenable)")));
1147 Log_RotationAge = 0;
1148 Log_RotationSize = 0;
1154 setvbuf(fh, NULL, LBF_MODE, 0);
1157 _setmode(_fileno(fh), _O_TEXT); /* use CRLF line endings on Windows */
1160 /* On Windows, need to interlock against data-transfer thread */
1162 EnterCriticalSection(&sysfileSection);
1167 LeaveCriticalSection(&sysfileSection);
1170 /* instead of pfree'ing filename, remember it for next time */
1171 if (last_csvfile_name != NULL)
1172 pfree(last_csvfile_name);
1173 last_csvfile_name = filename;
1176 set_next_rotation_time();
1182 * construct logfile name using timestamp information
1184 * Result is palloc'd.
1187 logfile_getname(pg_time_t timestamp, char *suffix)
1192 filename = palloc(MAXPGPATH);
1194 snprintf(filename, MAXPGPATH, "%s/", Log_directory);
1196 len = strlen(filename);
1198 if (strchr(Log_filename, '%'))
1200 /* treat it as a strftime pattern */
1201 pg_strftime(filename + len, MAXPGPATH - len, Log_filename,
1202 pg_localtime(×tamp, log_timezone));
1206 /* no strftime escapes, so append timestamp to new filename */
1207 snprintf(filename + len, MAXPGPATH - len, "%s.%lu",
1208 Log_filename, (unsigned long) timestamp);
1213 len = strlen(filename);
1214 if (len > 4 && (strcmp(filename + (len - 4), ".log") == 0))
1216 strncpy(filename + len, suffix, MAXPGPATH - len);
1223 * Determine the next planned rotation time, and store in next_rotation_time.
1226 set_next_rotation_time(void)
1232 /* nothing to do if time-based rotation is disabled */
1233 if (Log_RotationAge <= 0)
1237 * The requirements here are to choose the next time > now that is a
1238 * "multiple" of the log rotation interval. "Multiple" can be interpreted
1239 * fairly loosely. In this version we align to log_timezone rather than
1242 rotinterval = Log_RotationAge * SECS_PER_MINUTE; /* convert to seconds */
1243 now = (pg_time_t) time(NULL);
1244 tm = pg_localtime(&now, log_timezone);
1245 now += tm->tm_gmtoff;
1246 now -= now % rotinterval;
1248 now -= tm->tm_gmtoff;
1249 next_rotation_time = now;
1252 /* --------------------------------
1253 * signal handler routines
1254 * --------------------------------
1257 /* SIGHUP: set flag to reload config file */
1259 sigHupHandler(SIGNAL_ARGS)
1264 /* SIGUSR1: set flag to rotate logfile */
1266 sigUsr1Handler(SIGNAL_ARGS)
1268 rotation_requested = true;