diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index d078501814c7a55f6fadac59b2da56921893e3cb..0ad6804e55204355849faa3da273ec3fac7eb6b7 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -315,6 +315,16 @@ StartReplication(StartReplicationCmd * cmd) { StringInfoData buf; + /* + * Let postmaster know that we're streaming. Once we've declared us as + * a WAL sender process, postmaster will let us outlive the bgwriter and + * kill us last in the shutdown sequence, so we get a chance to stream + * all remaining WAL at shutdown, including the shutdown checkpoint. + * Note that there's no going back, and we mustn't write any WAL records + * after this. + */ + MarkPostmasterChildWalSender(); + /* * Check that we're logging enough information in the WAL for * log-shipping. diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 155bd751bf2ce6f194a7a0f9024af16ba83bafd8..391d6a6ea046e45b88a8c9bd3d47ea7e25fa18e7 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -49,6 +49,8 @@ * * Actually there is a fourth state, WALSENDER. This is just like ACTIVE, * but carries the extra information that the child is a WAL sender. + * WAL senders too start in ACTIVE state, but switch to WALSENDER once they + * start streaming the WAL (and they never go back to ACTIVE after that). */ #define PM_CHILD_UNUSED 0 /* these values must fit in sig_atomic_t */ @@ -225,8 +227,25 @@ MarkPostmasterChildActive(void) Assert(slot > 0 && slot <= PMSignalState->num_child_flags); slot--; Assert(PMSignalState->PMChildFlags[slot] == PM_CHILD_ASSIGNED); - PMSignalState->PMChildFlags[slot] = - (am_walsender ? PM_CHILD_WALSENDER : PM_CHILD_ACTIVE); + PMSignalState->PMChildFlags[slot] = PM_CHILD_ACTIVE; +} + +/* + * MarkPostmasterChildWalSender - mark a postmaster child as a WAL sender + * process. This is called in the child process, sometime after marking the + * child as active. + */ +void +MarkPostmasterChildWalSender(void) +{ + int slot = MyPMChildSlot; + + Assert(am_walsender); + + Assert(slot > 0 && slot <= PMSignalState->num_child_flags); + slot--; + Assert(PMSignalState->PMChildFlags[slot] == PM_CHILD_ACTIVE); + PMSignalState->PMChildFlags[slot] = PM_CHILD_WALSENDER; } /* diff --git a/src/include/storage/pmsignal.h b/src/include/storage/pmsignal.h index 2deff728ecd3e38fcfa0a8de5b4ac9f677b21e7a..97bdc7bc86d7f5d78e8ede1eee4edd8742e94ad8 100644 --- a/src/include/storage/pmsignal.h +++ b/src/include/storage/pmsignal.h @@ -48,6 +48,7 @@ extern bool ReleasePostmasterChildSlot(int slot); extern bool IsPostmasterChildWalSender(int slot); extern void MarkPostmasterChildActive(void); extern void MarkPostmasterChildInactive(void); +extern void MarkPostmasterChildWalSender(void); extern bool PostmasterIsAlive(bool amDirectChild); #endif /* PMSIGNAL_H */