Commit 8f5d65e9 authored by Heikki Linnakangas's avatar Heikki Linnakangas

Treat a WAL sender process that hasn't started streaming yet as a regular

backend, as far as the postmaster shutdown logic is concerned. That means,
fast shutdown will wait for WAL sender processes to exit before signaling
bgwriter to finish. This avoids race conditions between a base backup stopping
or starting, and bgwriter writing the shutdown checkpoint WAL record. We don't
want e.g the end-of-backup WAL record to be written after the shutdown
checkpoint.
parent fcd810c6
...@@ -315,6 +315,16 @@ StartReplication(StartReplicationCmd * cmd) ...@@ -315,6 +315,16 @@ StartReplication(StartReplicationCmd * cmd)
{ {
StringInfoData buf; 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 * Check that we're logging enough information in the WAL for
* log-shipping. * log-shipping.
......
...@@ -49,6 +49,8 @@ ...@@ -49,6 +49,8 @@
* *
* Actually there is a fourth state, WALSENDER. This is just like ACTIVE, * Actually there is a fourth state, WALSENDER. This is just like ACTIVE,
* but carries the extra information that the child is a WAL sender. * 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 */ #define PM_CHILD_UNUSED 0 /* these values must fit in sig_atomic_t */
...@@ -225,8 +227,25 @@ MarkPostmasterChildActive(void) ...@@ -225,8 +227,25 @@ MarkPostmasterChildActive(void)
Assert(slot > 0 && slot <= PMSignalState->num_child_flags); Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
slot--; slot--;
Assert(PMSignalState->PMChildFlags[slot] == PM_CHILD_ASSIGNED); Assert(PMSignalState->PMChildFlags[slot] == PM_CHILD_ASSIGNED);
PMSignalState->PMChildFlags[slot] = PMSignalState->PMChildFlags[slot] = PM_CHILD_ACTIVE;
(am_walsender ? PM_CHILD_WALSENDER : 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;
} }
/* /*
......
...@@ -48,6 +48,7 @@ extern bool ReleasePostmasterChildSlot(int slot); ...@@ -48,6 +48,7 @@ extern bool ReleasePostmasterChildSlot(int slot);
extern bool IsPostmasterChildWalSender(int slot); extern bool IsPostmasterChildWalSender(int slot);
extern void MarkPostmasterChildActive(void); extern void MarkPostmasterChildActive(void);
extern void MarkPostmasterChildInactive(void); extern void MarkPostmasterChildInactive(void);
extern void MarkPostmasterChildWalSender(void);
extern bool PostmasterIsAlive(bool amDirectChild); extern bool PostmasterIsAlive(bool amDirectChild);
#endif /* PMSIGNAL_H */ #endif /* PMSIGNAL_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment