postgres.git / summary / log / commit / refs

commit    38b27792eae99f5b4db2411f5c57ef70f850df5f
Author:   Robert Haas <rhaas@postgresql.org>
Date:     Sun Apr 03 23:42:00 2011 +0000
First released in: 9.1.0

    Avoid possible hang during smart shutdown.
    
    If a smart shutdown occurs just as a child is starting up, and the
    child subsequently becomes a walsender, there is a race condition:
    the postmaster might count the exstant backends, determine that there
    is one normal backend, and wait for it to die off.  Had the walsender
    transition already occurred before the postmaster counted, it would
    have proceeded with the shutdown.
    
    To fix this, have each child that transforms into a walsender kick
    the postmaster just after doing so, so that the state machine is
    certain to advance.
    
    Fujii Masao


src/backend/postmaster/postmaster.c | 11 +++++++++-- src/backend/replication/walsender.c | 1 + src/include/storage/pmsignal.h | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 997af5bf072..93e59258cc5 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -2890,8 +2890,8 @@ LogChildExit(int lev, const char *procname, int pid, int exitstatus) /* * Advance the postmaster's state machine and take actions as appropriate * - * This is common code for pmdie() and reaper(), which receive the signals - * that might mean we need to change state. + * This is common code for pmdie(), reaper() and sigusr1_handler(), which + * receive the signals that might mean we need to change state. */ static void PostmasterStateMachine(void) @@ -4284,6 +4284,13 @@ sigusr1_handler(SIGNAL_ARGS) WalReceiverPID = StartWalReceiver(); } + if (CheckPostmasterSignal(PMSIGNAL_ADVANCE_STATE_MACHINE) && + (pmState == PM_WAIT_BACKUP || pmState == PM_WAIT_BACKENDS)) + { + /* Advance postmaster's state machine */ + PostmasterStateMachine(); + } + if (CheckPromoteSignal() && StartupPID != 0 && (pmState == PM_STARTUP || pmState == PM_RECOVERY || pmState == PM_HOT_STANDBY || pmState == PM_WAIT_READONLY)) diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index dde773d79e1..1c11e7ff7a2 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -361,6 +361,7 @@ StartReplication(StartReplicationCmd * cmd) * after this. */ MarkPostmasterChildWalSender(); + SendPostmasterSignal(PMSIGNAL_ADVANCE_STATE_MACHINE); /* * Check that we're logging enough information in the WAL for diff --git a/src/include/storage/pmsignal.h b/src/include/storage/pmsignal.h index 97bdc7bc86d..0ca8ca0cc7e 100644 --- a/src/include/storage/pmsignal.h +++ b/src/include/storage/pmsignal.h @@ -29,6 +29,7 @@ typedef enum PMSIGNAL_START_AUTOVAC_LAUNCHER, /* start an autovacuum launcher */ PMSIGNAL_START_AUTOVAC_WORKER, /* start an autovacuum worker */ PMSIGNAL_START_WALRECEIVER, /* start a walreceiver */ + PMSIGNAL_ADVANCE_STATE_MACHINE, /* advance postmaster's state machine */ NUM_PMSIGNALS /* Must be last value of enum! */ } PMSignalReason; [parent: d518d6a16879]