diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 026850a1cf..dacd3e1dfe 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -1441,10 +1441,11 @@ $ sysctl -w vm.nr_hugepages=3170
This is the Immediate Shutdown mode.
The server will send SIGQUIT to all child
- processes and wait for them to terminate. Those that don't terminate
- within 5 seconds, will be sent SIGKILL by the
- master postgres 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 SIGKILL.
+ 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.
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 324bf7aad1..1757b4df37 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);
}
}
}