Skip to content

Commit 118b941

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 27394f7 commit 118b941

File tree

2 files changed

+35
-14
lines changed

2 files changed

+35
-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
bool IsBinaryUpgrade;
441442
#ifdef WIN32
@@ -4696,7 +4697,7 @@ MaxLivePostmasterChildren(void)
46964697

46974698
/*
46984699
* The following need to be available to the save/restore_backend_variables
4699-
* functions
4700+
* functions. They are marked NON_EXEC_STATIC in their home modules.
47004701
*/
47014702
extern slock_t *ShmemLock;
47024703
extern LWLock *LWLockArray;
@@ -4705,6 +4706,7 @@ extern PROC_HDR *ProcGlobal;
47054706
extern PGPROC *AuxiliaryProcs;
47064707
extern PMSignalData *PMSignalState;
47074708
extern pgsocket pgStatSock;
4709+
extern pg_time_t first_syslogger_file_time;
47084710

47094711
#ifndef WIN32
47104712
#define write_inheritable_socket(dest, src, childpid) ((*(dest) = (src)), true)
@@ -4756,6 +4758,7 @@ save_backend_variables(BackendParameters *param, Port *port,
47564758
param->PostmasterPid = PostmasterPid;
47574759
param->PgStartTime = PgStartTime;
47584760
param->PgReloadTime = PgReloadTime;
4761+
param->first_syslogger_file_time = first_syslogger_file_time;
47594762

47604763
param->redirection_done = redirection_done;
47614764
param->IsBinaryUpgrade = IsBinaryUpgrade;
@@ -4975,6 +4978,7 @@ restore_backend_variables(BackendParameters *param, Port *port)
49754978
PostmasterPid = param->PostmasterPid;
49764979
PgStartTime = param->PgStartTime;
49774980
PgReloadTime = param->PgReloadTime;
4981+
first_syslogger_file_time = param->first_syslogger_file_time;
49784982

49794983
redirection_done = param->redirection_done;
49804984
IsBinaryUpgrade = param->IsBinaryUpgrade;

src/backend/postmaster/syslogger.c

Lines changed: 30 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
@@ -91,6 +91,7 @@ static bool pipe_eof_seen = false;
9191
static bool rotation_disabled = false;
9292
static FILE *syslogFile = NULL;
9393
static FILE *csvlogFile = NULL;
94+
NON_EXEC_STATIC pg_time_t first_syslogger_file_time = 0;
9495
static char *last_file_name = NULL;
9596
static char *last_csv_file_name = NULL;
9697

@@ -284,6 +285,13 @@ SysLoggerMain(int argc, char *argv[])
284285
elog(FATAL, "could not create syslogger data transfer thread: %m");
285286
#endif /* WIN32 */
286287

288+
/*
289+
* Remember active logfile's name. We recompute this from the reference
290+
* time because passing down just the pg_time_t is a lot cheaper than
291+
* passing a whole file path in the EXEC_BACKEND case.
292+
*/
293+
last_file_name = logfile_getname(first_syslogger_file_time, NULL);
294+
287295
/* remember active logfile parameters */
288296
currentLogDir = pstrdup(Log_directory);
289297
currentLogFilename = pstrdup(Log_filename);
@@ -535,9 +543,18 @@ SysLogger_Start(void)
535543

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

542559
syslogFile = logfile_open(filename, "a", false);
543560

@@ -1017,8 +1034,12 @@ pipeThread(void *arg)
10171034
#endif /* WIN32 */
10181035

10191036
/*
1020-
* open the csv log file - we do this opportunistically, because
1037+
* Open the csv log file - we do this opportunistically, because
10211038
* we don't know if CSV logging will be wanted.
1039+
*
1040+
* This is only used the first time we open the csv log in a given syslogger
1041+
* process, not during rotations. As with opening the main log file, we
1042+
* always append in this situation.
10221043
*/
10231044
static void
10241045
open_csvlogfile(void)
@@ -1029,7 +1050,10 @@ open_csvlogfile(void)
10291050

10301051
csvlogFile = logfile_open(filename, "a", false);
10311052

1032-
pfree(filename);
1053+
if (last_csv_file_name != NULL) /* probably shouldn't happen */
1054+
pfree(last_csv_file_name);
1055+
1056+
last_csv_file_name = filename;
10331057
}
10341058

10351059
/*
@@ -1108,14 +1132,7 @@ logfile_rotate(bool time_based_rotation, int size_rotation_for)
11081132
* elapsed time and not something else, and (c) the computed file name is
11091133
* different from what we were previously logging into.
11101134
*
1111-
* Note: during the first rotation after forking off from the postmaster,
1112-
* last_file_name will be NULL. (We don't bother to set it in the
1113-
* postmaster because it ain't gonna work in the EXEC_BACKEND case.) So we
1114-
* will always append in that situation, even though truncating would
1115-
* usually be safe.
1116-
*
1117-
* For consistency, we treat CSV logs the same even though they aren't
1118-
* opened in the postmaster.
1135+
* Note: last_file_name should never be NULL here, but if it is, append.
11191136
*/
11201137
if (time_based_rotation || (size_rotation_for & LOG_DESTINATION_STDERR))
11211138
{

0 commit comments

Comments
 (0)