From 0cb117eb33558bc779df833480958a97227dcbc2 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 11 Feb 2004 22:25:02 +0000 Subject: [PATCH] Repair some problems in bgwriter start/stop logic. In particular, don't allow the bgwriter to start before the startup subprocess has finished ... it tends to crash otherwise. (The same problem may have existed for the checkpointer, I'm not entirely sure.) Remove some code that was redundant because the bgwriter is handled as a member of the backend list. --- src/backend/postmaster/postmaster.c | 65 +++++++++++++---------------- 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 12de05b6a6..2809cd9f5e 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -37,7 +37,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.365 2004/02/08 22:28:56 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.366 2004/02/11 22:25:02 tgl Exp $ * * NOTES * @@ -1079,7 +1079,8 @@ ServerLoop(void) timeout.tv_usec = 0; if (CheckPointPID == 0 && checkpointed && - Shutdown == NoShutdown && !FatalError && random_seed != 0) + StartupPID == 0 && Shutdown == NoShutdown && + !FatalError && random_seed != 0) { time_t now = time(NULL); @@ -1113,7 +1114,8 @@ ServerLoop(void) * this fails, we'll just try again later. */ if (BgWriterPID == 0 && BgWriterPercent > 0 && - Shutdown == NoShutdown && !FatalError && random_seed != 0) + StartupPID == 0 && Shutdown == NoShutdown && + !FatalError && random_seed != 0) { BgWriterPID = StartBackgroundWriter(); } @@ -1772,13 +1774,16 @@ pmdie(SIGNAL_ARGS) * * Wait for children to end their work and ShutdownDataBase. */ - if (BgWriterPID != 0) - kill(BgWriterPID, SIGTERM); if (Shutdown >= SmartShutdown) break; Shutdown = SmartShutdown; ereport(LOG, (errmsg("received smart shutdown request"))); + + /* Must tell bgwriter to quit, or it never will... */ + if (BgWriterPID != 0) + kill(BgWriterPID, SIGTERM); + if (DLGetHead(BackendList)) /* let reaper() handle this */ break; @@ -1803,47 +1808,39 @@ pmdie(SIGNAL_ARGS) /* * Fast Shutdown: * - * abort all children with SIGTERM (rollback active transactions + * Abort all children with SIGTERM (rollback active transactions * and exit) and ShutdownDataBase when they are gone. */ - if (BgWriterPID != 0) - kill(BgWriterPID, SIGTERM); if (Shutdown >= FastShutdown) break; + Shutdown = FastShutdown; ereport(LOG, (errmsg("received fast shutdown request"))); - if (DLGetHead(BackendList)) /* let reaper() handle this */ + + if (DLGetHead(BackendList)) { - Shutdown = FastShutdown; if (!FatalError) { ereport(LOG, (errmsg("aborting any active transactions"))); SignalChildren(SIGTERM); + /* reaper() does the rest */ } break; } - if (Shutdown > NoShutdown) - { - Shutdown = FastShutdown; - break; - } - Shutdown = FastShutdown; /* * No children left. Shutdown data base system. + * + * Unlike the previous case, it is not an error for the shutdown + * process to be running already (we could get SIGTERM followed + * shortly later by SIGINT). */ if (StartupPID > 0 || FatalError) /* let reaper() handle * this */ break; - if (ShutdownPID > 0) - { - elog(PANIC, "shutdown process %d already running", - (int) ShutdownPID); - abort(); - } - - ShutdownPID = ShutdownDataBase(); + if (ShutdownPID == 0) + ShutdownPID = ShutdownDataBase(); break; case SIGQUIT: @@ -1854,8 +1851,6 @@ pmdie(SIGNAL_ARGS) * abort all children with SIGQUIT and exit without attempt to * properly shutdown data base system. */ - if (BgWriterPID != 0) - kill(BgWriterPID, SIGQUIT); ereport(LOG, (errmsg("received immediate shutdown request"))); if (ShutdownPID > 0) @@ -1973,12 +1968,6 @@ reaper(SIGNAL_ARGS) CheckPointPID = 0; checkpointed = time(NULL); - if (BgWriterPID == 0 && BgWriterPercent > 0 && - Shutdown == NoShutdown && !FatalError && random_seed != 0) - { - BgWriterPID = StartBackgroundWriter(); - } - /* * Go to shutdown mode if a shutdown request was pending. */ @@ -2101,8 +2090,8 @@ CleanupProc(int pid, if (!FatalError) { LogChildExit(LOG, - (pid == CheckPointPID) ? gettext("checkpoint process") : - (pid == BgWriterPID) ? gettext("bgwriter process") : + (pid == CheckPointPID) ? gettext("checkpoint process") : + (pid == BgWriterPID) ? gettext("bgwriter process") : gettext("server process"), pid, exitstatus); ereport(LOG, @@ -2844,7 +2833,8 @@ sigusr1_handler(SIGNAL_ARGS) * is currently disabled */ if (CheckPointPID == 0 && checkpointed && - Shutdown == NoShutdown && !FatalError && random_seed != 0) + StartupPID == 0 && Shutdown == NoShutdown && + !FatalError && random_seed != 0) { CheckPointPID = CheckPointDataBase(); /* note: if fork fails, CheckPointPID stays 0; nothing happens */ @@ -2975,6 +2965,7 @@ CountChildren(void) if (bp->pid != MyProcPid) cnt++; } + /* Checkpoint and bgwriter will be in the list, discount them */ if (CheckPointPID != 0) cnt--; if (BgWriterPID != 0) @@ -2983,10 +2974,10 @@ CountChildren(void) } /* - * Fire off a subprocess for startup/shutdown/checkpoint. + * Fire off a subprocess for startup/shutdown/checkpoint/bgwriter. * * Return value of SSDataBase is subprocess' PID, or 0 if failed to start subprocess - * (0 is returned only for checkpoint case). + * (0 is returned only for checkpoint/bgwriter cases). * * note: in the EXEC_BACKEND case, we delay the fork until argument list has been * established