PgStatPID = 0,
SysLoggerPID = 0;
+/* Startup process's status */
+typedef enum
+{
+ STARTUP_NOT_RUNNING,
+ STARTUP_RUNNING,
+ STARTUP_SIGNALED, /* we sent it a SIGQUIT or SIGKILL */
+ STARTUP_CRASHED
+} StartupStatusEnum;
+
+static StartupStatusEnum StartupStatus = STARTUP_NOT_RUNNING;
+
/* Startup/shutdown state */
#define NoShutdown 0
#define SmartShutdown 1
static int Shutdown = NoShutdown;
static bool FatalError = false; /* T if recovering from backend crash */
-static bool RecoveryError = false; /* T if WAL recovery failed */
/*
* We use a simple state machine to control startup, shutdown, and
* states, nor in PM_SHUTDOWN states (because we don't enter those states
* when trying to recover from a crash). It can be true in PM_STARTUP state,
* because we don't clear it until we've successfully started WAL redo.
- * Similarly, RecoveryError means that we have crashed during recovery, and
- * should not try to restart.
*/
typedef enum
{
*/
StartupPID = StartupDataBase();
Assert(StartupPID != 0);
+ StartupStatus = STARTUP_RUNNING;
pmState = PM_STARTUP;
/* Some workers may be scheduled to start now */
/* If we have lost the archiver, try to start a new one. */
if (PgArchPID == 0 && PgArchStartupAllowed())
- PgArchPID = pgarch_start();
+ PgArchPID = pgarch_start();
/* If we need to signal the autovacuum launcher, do so now */
if (avlauncher_needs_signal)
if (Shutdown > NoShutdown &&
(EXIT_STATUS_0(exitstatus) || EXIT_STATUS_1(exitstatus)))
{
+ StartupStatus = STARTUP_NOT_RUNNING;
pmState = PM_WAIT_BACKENDS;
/* PostmasterStateMachine logic does the rest */
continue;
{
ereport(LOG,
(errmsg("shutdown at recovery target")));
+ StartupStatus = STARTUP_NOT_RUNNING;
Shutdown = SmartShutdown;
TerminateChildren(SIGTERM);
pmState = PM_WAIT_BACKENDS;
/*
* After PM_STARTUP, any unexpected exit (including FATAL exit) of
* the startup process is catastrophic, so kill other children,
- * and set RecoveryError so we don't try to reinitialize after
- * they're gone. Exception: if FatalError is already set, that
- * implies we previously sent the startup process a SIGQUIT, so
+ * and set StartupStatus so we don't try to reinitialize after
+ * they're gone. Exception: if StartupStatus is STARTUP_SIGNALED,
+ * then we previously sent the startup process a SIGQUIT; so
* that's probably the reason it died, and we do want to try to
* restart in that case.
*/
if (!EXIT_STATUS_0(exitstatus))
{
- if (!FatalError)
- RecoveryError = true;
+ if (StartupStatus == STARTUP_SIGNALED)
+ StartupStatus = STARTUP_NOT_RUNNING;
+ else
+ StartupStatus = STARTUP_CRASHED;
HandleChildCrash(pid, exitstatus,
_("startup process"));
continue;
/*
* Startup succeeded, commence normal operations
*/
+ StartupStatus = STARTUP_NOT_RUNNING;
FatalError = false;
Assert(AbortStartTime == 0);
ReachedNormalRunning = true;
ReportBackgroundWorkerPID(rw); /* report child death */
LogChildExit(EXIT_STATUS_0(exitstatus) ? DEBUG1 : LOG,
- namebuf, pid, exitstatus);
+ namebuf, pid, exitstatus);
return true;
}
/* Take care of the startup process too */
if (pid == StartupPID)
+ {
StartupPID = 0;
+ StartupStatus = STARTUP_CRASHED;
+ }
else if (StartupPID != 0 && take_action)
{
ereport(DEBUG2,
(SendStop ? "SIGSTOP" : "SIGQUIT"),
(int) StartupPID)));
signal_child(StartupPID, (SendStop ? SIGSTOP : SIGQUIT));
+ StartupStatus = STARTUP_SIGNALED;
}
/* Take care of the bgwriter too */
}
/*
- * If recovery failed, or the user does not want an automatic restart
- * after backend crashes, wait for all non-syslogger children to exit, and
- * then exit postmaster. We don't try to reinitialize when recovery fails,
- * because more than likely it will just fail again and we will keep
- * trying forever.
+ * If the startup process failed, or the user does not want an automatic
+ * restart after backend crashes, wait for all non-syslogger children to
+ * exit, and then exit postmaster. We don't try to reinitialize when the
+ * startup process fails, because more than likely it will just fail again
+ * and we will keep trying forever.
*/
- if (pmState == PM_NO_CHILDREN && (RecoveryError || !restart_after_crash))
+ if (pmState == PM_NO_CHILDREN &&
+ (StartupStatus == STARTUP_CRASHED || !restart_after_crash))
ExitPostmaster(1);
/*
StartupPID = StartupDataBase();
Assert(StartupPID != 0);
+ StartupStatus = STARTUP_RUNNING;
pmState = PM_STARTUP;
/* crash recovery started, reset SIGKILL flag */
AbortStartTime = 0;
{
SignalChildren(signal);
if (StartupPID != 0)
+ {
signal_child(StartupPID, signal);
+ if (signal == SIGQUIT || signal == SIGKILL)
+ StartupStatus = STARTUP_SIGNALED;
+ }
if (BgWriterPID != 0)
signal_child(BgWriterPID, signal);
if (CheckpointerPID != 0)