Skip to content

Commit 63aba79

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 65f3335 commit 63aba79

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
@@ -437,6 +437,7 @@ typedef struct
437437
pid_t PostmasterPid;
438438
TimestampTz PgStartTime;
439439
TimestampTz PgReloadTime;
440+
pg_time_t first_syslogger_file_time;
440441
bool redirection_done;
441442
bool IsBinaryUpgrade;
442443
int max_safe_fds;
@@ -4704,14 +4705,15 @@ MaxLivePostmasterChildren(void)
47044705

47054706
/*
47064707
* The following need to be available to the save/restore_backend_variables
4707-
* functions
4708+
* functions. They are marked NON_EXEC_STATIC in their home modules.
47084709
*/
47094710
extern slock_t *ShmemLock;
47104711
extern LWLock *LWLockArray;
47114712
extern slock_t *ProcStructLock;
47124713
extern PGPROC *AuxiliaryProcs;
47134714
extern PMSignalData *PMSignalState;
47144715
extern pgsocket pgStatSock;
4716+
extern pg_time_t first_syslogger_file_time;
47154717

47164718
#ifndef WIN32
47174719
#define write_inheritable_socket(dest, src, childpid) ((*(dest) = (src)), true)
@@ -4764,6 +4766,7 @@ save_backend_variables(BackendParameters *param, Port *port,
47644766
param->PostmasterPid = PostmasterPid;
47654767
param->PgStartTime = PgStartTime;
47664768
param->PgReloadTime = PgReloadTime;
4769+
param->first_syslogger_file_time = first_syslogger_file_time;
47674770

47684771
param->redirection_done = redirection_done;
47694772
param->IsBinaryUpgrade = IsBinaryUpgrade;
@@ -4988,6 +4991,7 @@ restore_backend_variables(BackendParameters *param, Port *port)
49884991
PostmasterPid = param->PostmasterPid;
49894992
PgStartTime = param->PgStartTime;
49904993
PgReloadTime = param->PgReloadTime;
4994+
first_syslogger_file_time = param->first_syslogger_file_time;
49914995

49924996
redirection_done = param->redirection_done;
49934997
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
static Latch sysLoggerLatch;
@@ -290,6 +291,13 @@ SysLoggerMain(int argc, char *argv[])
290291
elog(FATAL, "could not create syslogger data transfer thread: %m");
291292
#endif /* WIN32 */
292293

294+
/*
295+
* Remember active logfile's name. We recompute this from the reference
296+
* time because passing down just the pg_time_t is a lot cheaper than
297+
* passing a whole file path in the EXEC_BACKEND case.
298+
*/
299+
last_file_name = logfile_getname(first_syslogger_file_time, NULL);
300+
293301
/* remember active logfile parameters */
294302
currentLogDir = pstrdup(Log_directory);
295303
currentLogFilename = pstrdup(Log_filename);
@@ -559,9 +567,18 @@ SysLogger_Start(void)
559567

560568
/*
561569
* The initial logfile is created right in the postmaster, to verify that
562-
* the Log_directory is writable.
570+
* the Log_directory is writable. We save the reference time so that
571+
* the syslogger child process can recompute this file name.
572+
*
573+
* It might look a bit strange to re-do this during a syslogger restart,
574+
* but we must do so since the postmaster closed syslogFile after the
575+
* previous fork (and remembering that old file wouldn't be right anyway).
576+
* Note we always append here, we won't overwrite any existing file. This
577+
* is consistent with the normal rules, because by definition this is not
578+
* a time-based rotation.
563579
*/
564-
filename = logfile_getname(time(NULL), NULL);
580+
first_syslogger_file_time = time(NULL);
581+
filename = logfile_getname(first_syslogger_file_time, NULL);
565582

566583
syslogFile = logfile_open(filename, "a", false);
567584

@@ -1045,8 +1062,12 @@ pipeThread(void *arg)
10451062
#endif /* WIN32 */
10461063

10471064
/*
1048-
* open the csv log file - we do this opportunistically, because
1065+
* Open the csv log file - we do this opportunistically, because
10491066
* we don't know if CSV logging will be wanted.
1067+
*
1068+
* This is only used the first time we open the csv log in a given syslogger
1069+
* process, not during rotations. As with opening the main log file, we
1070+
* always append in this situation.
10501071
*/
10511072
static void
10521073
open_csvlogfile(void)
@@ -1057,7 +1078,10 @@ open_csvlogfile(void)
10571078

10581079
csvlogFile = logfile_open(filename, "a", false);
10591080

1060-
pfree(filename);
1081+
if (last_csv_file_name != NULL) /* probably shouldn't happen */
1082+
pfree(last_csv_file_name);
1083+
1084+
last_csv_file_name = filename;
10611085
}
10621086

10631087
/*
@@ -1136,14 +1160,7 @@ logfile_rotate(bool time_based_rotation, int size_rotation_for)
11361160
* elapsed time and not something else, and (c) the computed file name is
11371161
* different from what we were previously logging into.
11381162
*
1139-
* Note: during the first rotation after forking off from the postmaster,
1140-
* last_file_name will be NULL. (We don't bother to set it in the
1141-
* postmaster because it ain't gonna work in the EXEC_BACKEND case.) So we
1142-
* will always append in that situation, even though truncating would
1143-
* usually be safe.
1144-
*
1145-
* For consistency, we treat CSV logs the same even though they aren't
1146-
* opened in the postmaster.
1163+
* Note: last_file_name should never be NULL here, but if it is, append.
11471164
*/
11481165
if (time_based_rotation || (size_rotation_for & LOG_DESTINATION_STDERR))
11491166
{

0 commit comments

Comments
 (0)