diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index 026850a1cf5547e56c0a540679e15c4ad3f76d8a..dacd3e1dfefff5f448475888e236c68f0e571233 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -1441,10 +1441,11 @@ $ <userinput>sysctl -w vm.nr_hugepages=3170</userinput> <para> This is the <firstterm>Immediate Shutdown</firstterm> mode. The server will send <systemitem>SIGQUIT</systemitem> to all child - processes and wait for them to terminate. Those that don't terminate - within 5 seconds, will be sent <systemitem>SIGKILL</systemitem> by the - master <command>postgres</command> process, which will then terminate - without further waiting. This will lead to recovery (by + processes and wait for them to terminate. If any do not terminate + within 5 seconds, they will be sent <systemitem>SIGKILL</systemitem>. + The master server process exits as soon as all child processes have + exited, without doing normal database shutdown processing. + This will lead to recovery (by replaying the WAL log) upon next start-up. This is recommended only in emergencies. </para> diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 324bf7aad148f144c8c295fab2ad2b816f37ff7d..1757b4df37e1a76c07942dfa61e38a0777919190 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -324,8 +324,10 @@ typedef enum static PMState pmState = PM_INIT; -/* Start time of abort processing at immediate shutdown or child crash */ -static time_t AbortStartTime; +/* Start time of SIGKILL timeout during immediate shutdown or child crash */ +/* Zero means timeout is not running */ +static time_t AbortStartTime = 0; +/* Length of said timeout */ #define SIGKILL_CHILDREN_AFTER_SECS 5 static bool ReachedNormalRunning = false; /* T if we've reached PM_RUN */ @@ -1419,7 +1421,8 @@ checkDataDir(void) * In normal conditions we wait at most one minute, to ensure that the other * background tasks handled by ServerLoop get done even when no requests are * arriving. However, if there are background workers waiting to be started, - * we don't actually sleep so that they are quickly serviced. + * we don't actually sleep so that they are quickly serviced. Other exception + * cases are as shown in the code. */ static void DetermineSleepTime(struct timeval * timeout) @@ -1433,11 +1436,12 @@ DetermineSleepTime(struct timeval * timeout) if (Shutdown > NoShutdown || (!StartWorkerNeeded && !HaveCrashedWorker)) { - if (AbortStartTime > 0) + if (AbortStartTime != 0) { /* time left to abort; clamp to 0 in case it already expired */ - timeout->tv_sec = Max(SIGKILL_CHILDREN_AFTER_SECS - - (time(NULL) - AbortStartTime), 0); + timeout->tv_sec = SIGKILL_CHILDREN_AFTER_SECS - + (time(NULL) - AbortStartTime); + timeout->tv_sec = Max(timeout->tv_sec, 0); timeout->tv_usec = 0; } else @@ -1707,20 +1711,13 @@ ServerLoop(void) * Note we also do this during recovery from a process crash. */ if ((Shutdown >= ImmediateShutdown || (FatalError && !SendStop)) && - AbortStartTime > 0 && - now - AbortStartTime >= SIGKILL_CHILDREN_AFTER_SECS) + AbortStartTime != 0 && + (now - AbortStartTime) >= SIGKILL_CHILDREN_AFTER_SECS) { /* We were gentle with them before. Not anymore */ TerminateChildren(SIGKILL); /* reset flag so we don't SIGKILL again */ AbortStartTime = 0; - - /* - * Additionally, unless we're recovering from a process crash, - * it's now the time for postmaster to abandon ship. - */ - if (!FatalError) - ExitPostmaster(1); } } }