1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-27 12:41:57 +03:00

Add condition variable for walreceiver shutdown.

Use this new CV to wait for walreceiver shutdown without a sleep/poll
loop, while also benefiting from standard postmaster death handling.

Discussion: https://postgr.es/m/CA%2BhUKGK1607VmtrDUHQXrsooU%3Dap4g4R2yaoByWOOA3m8xevUQ%40mail.gmail.com
This commit is contained in:
Thomas Munro
2021-03-12 19:07:27 +13:00
parent 600f2f50b7
commit de829ddf23
6 changed files with 41 additions and 13 deletions

View File

@ -23,6 +23,7 @@
#include <signal.h>
#include "access/xlog_internal.h"
#include "pgstat.h"
#include "postmaster/startup.h"
#include "replication/walreceiver.h"
#include "storage/pmsignal.h"
@ -62,6 +63,7 @@ WalRcvShmemInit(void)
/* First time through, so initialize */
MemSet(WalRcv, 0, WalRcvShmemSize());
WalRcv->walRcvState = WALRCV_STOPPED;
ConditionVariableInit(&WalRcv->walRcvStoppedCV);
SpinLockInit(&WalRcv->mutex);
pg_atomic_init_u64(&WalRcv->writtenUpto, 0);
WalRcv->latch = NULL;
@ -95,12 +97,18 @@ WalRcvRunning(void)
if ((now - startTime) > WALRCV_STARTUP_TIMEOUT)
{
bool stopped = false;
SpinLockAcquire(&walrcv->mutex);
if (walrcv->walRcvState == WALRCV_STARTING)
{
state = walrcv->walRcvState = WALRCV_STOPPED;
stopped = true;
}
SpinLockRelease(&walrcv->mutex);
if (stopped)
ConditionVariableBroadcast(&walrcv->walRcvStoppedCV);
}
}
@ -140,12 +148,18 @@ WalRcvStreaming(void)
if ((now - startTime) > WALRCV_STARTUP_TIMEOUT)
{
bool stopped = false;
SpinLockAcquire(&walrcv->mutex);
if (walrcv->walRcvState == WALRCV_STARTING)
{
state = walrcv->walRcvState = WALRCV_STOPPED;
stopped = true;
}
SpinLockRelease(&walrcv->mutex);
if (stopped)
ConditionVariableBroadcast(&walrcv->walRcvStoppedCV);
}
}
@ -165,6 +179,7 @@ ShutdownWalRcv(void)
{
WalRcvData *walrcv = WalRcv;
pid_t walrcvpid = 0;
bool stopped = false;
/*
* Request walreceiver to stop. Walreceiver will switch to WALRCV_STOPPED
@ -178,6 +193,7 @@ ShutdownWalRcv(void)
break;
case WALRCV_STARTING:
walrcv->walRcvState = WALRCV_STOPPED;
stopped = true;
break;
case WALRCV_STREAMING:
@ -191,6 +207,10 @@ ShutdownWalRcv(void)
}
SpinLockRelease(&walrcv->mutex);
/* Unnecessary but consistent. */
if (stopped)
ConditionVariableBroadcast(&walrcv->walRcvStoppedCV);
/*
* Signal walreceiver process if it was still running.
*/
@ -201,16 +221,11 @@ ShutdownWalRcv(void)
* Wait for walreceiver to acknowledge its death by setting state to
* WALRCV_STOPPED.
*/
ConditionVariablePrepareToSleep(&walrcv->walRcvStoppedCV);
while (WalRcvRunning())
{
/*
* This possibly-long loop needs to handle interrupts of startup
* process.
*/
HandleStartupProcInterrupts();
pg_usleep(100000); /* 100ms */
}
ConditionVariableSleep(&walrcv->walRcvStoppedCV,
WAIT_EVENT_WALRCV_EXIT);
ConditionVariableCancelSleep();
}
/*