Skip to content

Commit 706f792

Browse files
committed
Fix syslogger so that log_truncate_on_rotation works in the first rotation.
In the original coding of the log rotation stuff, we did not bother to make the truncation logic work for the very first rotation after postmaster start (or after a syslogger crash and restart). It just always appended in that case. It did not seem terribly important at the time, but we've recently had two separate complaints from people who expected it to work unsurprisingly. (Both users tend to restart the postmaster about as often as a log rotation is configured to happen, which is maybe not typical use, but still...) Since the initial log file is opened in the postmaster, fixing this requires passing down some more state to the syslogger child process. It's always been like this, so back-patch to all supported branches.
1 parent 85509b9 commit 706f792

File tree

2 files changed

+34
-14
lines changed

2 files changed

+34
-14
lines changed

src/backend/postmaster/postmaster.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ typedef struct
436436
pid_t PostmasterPid;
437437
TimestampTz PgStartTime;
438438
TimestampTz PgReloadTime;
439+
pg_time_t first_syslogger_file_time;
439440
bool redirection_done;
440441
#ifdef WIN32
441442
HANDLE PostmasterHandle;
@@ -4624,7 +4625,7 @@ MaxLivePostmasterChildren(void)
46244625

46254626
/*
46264627
* The following need to be available to the save/restore_backend_variables
4627-
* functions
4628+
* functions. They are marked NON_EXEC_STATIC in their home modules.
46284629
*/
46294630
extern slock_t *ShmemLock;
46304631
extern LWLock *LWLockArray;
@@ -4633,6 +4634,7 @@ extern PROC_HDR *ProcGlobal;
46334634
extern PGPROC *AuxiliaryProcs;
46344635
extern PMSignalData *PMSignalState;
46354636
extern pgsocket pgStatSock;
4637+
extern pg_time_t first_syslogger_file_time;
46364638

46374639
#ifndef WIN32
46384640
#define write_inheritable_socket(dest, src, childpid) ((*(dest) = (src)), true)
@@ -4684,6 +4686,7 @@ save_backend_variables(BackendParameters * param, Port *port,
46844686
param->PostmasterPid = PostmasterPid;
46854687
param->PgStartTime = PgStartTime;
46864688
param->PgReloadTime = PgReloadTime;
4689+
param->first_syslogger_file_time = first_syslogger_file_time;
46874690

46884691
param->redirection_done = redirection_done;
46894692

@@ -4902,6 +4905,7 @@ restore_backend_variables(BackendParameters * param, Port *port)
49024905
PostmasterPid = param->PostmasterPid;
49034906
PgStartTime = param->PgStartTime;
49044907
PgReloadTime = param->PgReloadTime;
4908+
first_syslogger_file_time = param->first_syslogger_file_time;
49054909

49064910
redirection_done = param->redirection_done;
49074911

src/backend/postmaster/syslogger.c

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
*
33
* syslogger.c
44
*
5-
* The system logger (syslogger) is new in Postgres 8.0. It catches all
5+
* The system logger (syslogger) appeared in Postgres 8.0. It catches all
66
* stderr output from the postmaster, backends, and other subprocesses
77
* by redirecting to a pipe, and writes it to a set of logfiles.
88
* It's possible to have size and age limits for the logfile configured
@@ -90,6 +90,7 @@ static bool pipe_eof_seen = false;
9090
static bool rotation_disabled = false;
9191
static FILE *syslogFile = NULL;
9292
static FILE *csvlogFile = NULL;
93+
NON_EXEC_STATIC pg_time_t first_syslogger_file_time = 0;
9394
static char *last_file_name = NULL;
9495
static char *last_csv_file_name = NULL;
9596

@@ -281,6 +282,13 @@ SysLoggerMain(int argc, char *argv[])
281282
elog(FATAL, "could not create syslogger data transfer thread: %m");
282283
#endif /* WIN32 */
283284

285+
/*
286+
* Remember active logfile's name. We recompute this from the reference
287+
* time because passing down just the pg_time_t is a lot cheaper than
288+
* passing a whole file path in the EXEC_BACKEND case.
289+
*/
290+
last_file_name = logfile_getname(first_syslogger_file_time, NULL);
291+
284292
/* remember active logfile parameters */
285293
currentLogDir = pstrdup(Log_directory);
286294
currentLogFilename = pstrdup(Log_filename);
@@ -532,9 +540,18 @@ SysLogger_Start(void)
532540

533541
/*
534542
* The initial logfile is created right in the postmaster, to verify that
535-
* the Log_directory is writable.
543+
* the Log_directory is writable. We save the reference time so that
544+
* the syslogger child process can recompute this file name.
545+
*
546+
* It might look a bit strange to re-do this during a syslogger restart,
547+
* but we must do so since the postmaster closed syslogFile after the
548+
* previous fork (and remembering that old file wouldn't be right anyway).
549+
* Note we always append here, we won't overwrite any existing file. This
550+
* is consistent with the normal rules, because by definition this is not
551+
* a time-based rotation.
536552
*/
537-
filename = logfile_getname(time(NULL), NULL);
553+
first_syslogger_file_time = time(NULL);
554+
filename = logfile_getname(first_syslogger_file_time, NULL);
538555

539556
syslogFile = fopen(filename, "a");
540557

@@ -1022,8 +1039,12 @@ pipeThread(void *arg)
10221039
#endif /* WIN32 */
10231040

10241041
/*
1025-
* open the csv log file - we do this opportunistically, because
1042+
* Open the csv log file - we do this opportunistically, because
10261043
* we don't know if CSV logging will be wanted.
1044+
*
1045+
* This is only used the first time we open the csv log in a given syslogger
1046+
* process, not during rotations. As with opening the main log file, we
1047+
* always append in this situation.
10271048
*/
10281049
static void
10291050
open_csvlogfile(void)
@@ -1049,8 +1070,10 @@ open_csvlogfile(void)
10491070

10501071
csvlogFile = fh;
10511072

1052-
pfree(filename);
1073+
if (last_csv_file_name != NULL) /* probably shouldn't happen */
1074+
pfree(last_csv_file_name);
10531075

1076+
last_csv_file_name = filename;
10541077
}
10551078

10561079
/*
@@ -1085,14 +1108,7 @@ logfile_rotate(bool time_based_rotation, int size_rotation_for)
10851108
* elapsed time and not something else, and (c) the computed file name is
10861109
* different from what we were previously logging into.
10871110
*
1088-
* Note: during the first rotation after forking off from the postmaster,
1089-
* last_file_name will be NULL. (We don't bother to set it in the
1090-
* postmaster because it ain't gonna work in the EXEC_BACKEND case.) So we
1091-
* will always append in that situation, even though truncating would
1092-
* usually be safe.
1093-
*
1094-
* For consistency, we treat CSV logs the same even though they aren't
1095-
* opened in the postmaster.
1111+
* Note: last_file_name should never be NULL here, but if it is, append.
10961112
*/
10971113
if (time_based_rotation || (size_rotation_for & LOG_DESTINATION_STDERR))
10981114
{

0 commit comments

Comments
 (0)