Commit 00f690a2 authored by Fujii Masao's avatar Fujii Masao

Revert "Get rid of the dedicated latch for signaling the startup process".

Revert ac22929a, as well as the followup fix 113d3591. Because it broke
the assumption that the startup process waiting for the recovery conflict
on buffer pin should be waken up only by buffer unpin or the timeout enabled
in ResolveRecoveryConflictWithBufferPin(). It caused, for example,
SIGHUP signal handler or walreceiver process to wake that startup process
up unnecessarily frequently.

Additionally, add the comments about why that dedicated latch that
the reverted patch tried to get rid of should not be removed.

Thanks to Kyotaro Horiguchi for the discussion.

Author: Fujii Masao
Discussion: https://postgr.es/m/d8c0c608-021b-3c73-fffd-3240829ee986@oss.nttdata.com
parent 88e014c1
...@@ -681,8 +681,18 @@ typedef struct XLogCtlData ...@@ -681,8 +681,18 @@ typedef struct XLogCtlData
* recoveryWakeupLatch is used to wake up the startup process to continue * recoveryWakeupLatch is used to wake up the startup process to continue
* WAL replay, if it is waiting for WAL to arrive or failover trigger file * WAL replay, if it is waiting for WAL to arrive or failover trigger file
* to appear. * to appear.
*
* Note that the startup process also uses another latch, its procLatch,
* to wait for recovery conflict. If we get rid of recoveryWakeupLatch for
* signaling the startup process in favor of using its procLatch, which
* comports better with possible generic signal handlers using that latch.
* But we should not do that because the startup process doesn't assume
* that it's waken up by walreceiver process or SIGHUP signal handler
* while it's waiting for recovery conflict. The separate latches,
* recoveryWakeupLatch and procLatch, should be used for inter-process
* communication for WAL replay and recovery conflict, respectively.
*/ */
Latch *recoveryWakeupLatch; Latch recoveryWakeupLatch;
/* /*
* During recovery, we keep a copy of the latest checkpoint record here. * During recovery, we keep a copy of the latest checkpoint record here.
...@@ -5186,6 +5196,7 @@ XLOGShmemInit(void) ...@@ -5186,6 +5196,7 @@ XLOGShmemInit(void)
SpinLockInit(&XLogCtl->Insert.insertpos_lck); SpinLockInit(&XLogCtl->Insert.insertpos_lck);
SpinLockInit(&XLogCtl->info_lck); SpinLockInit(&XLogCtl->info_lck);
SpinLockInit(&XLogCtl->ulsn_lck); SpinLockInit(&XLogCtl->ulsn_lck);
InitSharedLatch(&XLogCtl->recoveryWakeupLatch);
} }
/* /*
...@@ -6121,7 +6132,7 @@ recoveryApplyDelay(XLogReaderState *record) ...@@ -6121,7 +6132,7 @@ recoveryApplyDelay(XLogReaderState *record)
while (true) while (true)
{ {
ResetLatch(MyLatch); ResetLatch(&XLogCtl->recoveryWakeupLatch);
/* might change the trigger file's location */ /* might change the trigger file's location */
HandleStartupProcInterrupts(); HandleStartupProcInterrupts();
...@@ -6140,7 +6151,7 @@ recoveryApplyDelay(XLogReaderState *record) ...@@ -6140,7 +6151,7 @@ recoveryApplyDelay(XLogReaderState *record)
elog(DEBUG2, "recovery apply delay %ld milliseconds", msecs); elog(DEBUG2, "recovery apply delay %ld milliseconds", msecs);
(void) WaitLatch(MyLatch, (void) WaitLatch(&XLogCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
msecs, msecs,
WAIT_EVENT_RECOVERY_APPLY_DELAY); WAIT_EVENT_RECOVERY_APPLY_DELAY);
...@@ -6469,11 +6480,11 @@ StartupXLOG(void) ...@@ -6469,11 +6480,11 @@ StartupXLOG(void)
} }
/* /*
* Advertise our latch that other processes can use to wake us up * Take ownership of the wakeup latch if we're going to sleep during
* if we're going to sleep during recovery. * recovery.
*/ */
if (ArchiveRecoveryRequested) if (ArchiveRecoveryRequested)
XLogCtl->recoveryWakeupLatch = &MyProc->procLatch; OwnLatch(&XLogCtl->recoveryWakeupLatch);
/* Set up XLOG reader facility */ /* Set up XLOG reader facility */
MemSet(&private, 0, sizeof(XLogPageReadPrivate)); MemSet(&private, 0, sizeof(XLogPageReadPrivate));
...@@ -7484,11 +7495,11 @@ StartupXLOG(void) ...@@ -7484,11 +7495,11 @@ StartupXLOG(void)
ResetUnloggedRelations(UNLOGGED_RELATION_INIT); ResetUnloggedRelations(UNLOGGED_RELATION_INIT);
/* /*
* We don't need the latch anymore. It's not strictly necessary to reset * We don't need the latch anymore. It's not strictly necessary to disown
* it to NULL, but let's do it for the sake of tidiness. * it, but let's do it for the sake of tidiness.
*/ */
if (ArchiveRecoveryRequested) if (ArchiveRecoveryRequested)
XLogCtl->recoveryWakeupLatch = NULL; DisownLatch(&XLogCtl->recoveryWakeupLatch);
/* /*
* We are now done reading the xlog from stream. Turn off streaming * We are now done reading the xlog from stream. Turn off streaming
...@@ -12300,12 +12311,12 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess, ...@@ -12300,12 +12311,12 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
wait_time = wal_retrieve_retry_interval - wait_time = wal_retrieve_retry_interval -
TimestampDifferenceMilliseconds(last_fail_time, now); TimestampDifferenceMilliseconds(last_fail_time, now);
(void) WaitLatch(MyLatch, (void) WaitLatch(&XLogCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_LATCH_SET | WL_TIMEOUT |
WL_EXIT_ON_PM_DEATH, WL_EXIT_ON_PM_DEATH,
wait_time, wait_time,
WAIT_EVENT_RECOVERY_RETRIEVE_RETRY_INTERVAL); WAIT_EVENT_RECOVERY_RETRIEVE_RETRY_INTERVAL);
ResetLatch(MyLatch); ResetLatch(&XLogCtl->recoveryWakeupLatch);
now = GetCurrentTimestamp(); now = GetCurrentTimestamp();
/* Handle interrupt signals of startup process */ /* Handle interrupt signals of startup process */
...@@ -12559,11 +12570,11 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess, ...@@ -12559,11 +12570,11 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
* to react to a trigger file promptly and to check if the * to react to a trigger file promptly and to check if the
* WAL receiver is still active. * WAL receiver is still active.
*/ */
(void) WaitLatch(MyLatch, (void) WaitLatch(&XLogCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_LATCH_SET | WL_TIMEOUT |
WL_EXIT_ON_PM_DEATH, WL_EXIT_ON_PM_DEATH,
5000L, WAIT_EVENT_RECOVERY_WAL_STREAM); 5000L, WAIT_EVENT_RECOVERY_WAL_STREAM);
ResetLatch(MyLatch); ResetLatch(&XLogCtl->recoveryWakeupLatch);
break; break;
} }
...@@ -12735,8 +12746,7 @@ CheckPromoteSignal(void) ...@@ -12735,8 +12746,7 @@ CheckPromoteSignal(void)
void void
WakeupRecovery(void) WakeupRecovery(void)
{ {
if (XLogCtl->recoveryWakeupLatch) SetLatch(&XLogCtl->recoveryWakeupLatch);
SetLatch(XLogCtl->recoveryWakeupLatch);
} }
/* /*
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
/* /*
* Flags set by interrupt handlers for later service in the redo loop. * Flags set by interrupt handlers for later service in the redo loop.
*/ */
static volatile sig_atomic_t got_SIGHUP = false;
static volatile sig_atomic_t shutdown_requested = false; static volatile sig_atomic_t shutdown_requested = false;
static volatile sig_atomic_t promote_signaled = false; static volatile sig_atomic_t promote_signaled = false;
...@@ -48,6 +49,7 @@ static volatile sig_atomic_t in_restore_command = false; ...@@ -48,6 +49,7 @@ static volatile sig_atomic_t in_restore_command = false;
/* Signal handlers */ /* Signal handlers */
static void StartupProcTriggerHandler(SIGNAL_ARGS); static void StartupProcTriggerHandler(SIGNAL_ARGS);
static void StartupProcSigHupHandler(SIGNAL_ARGS);
/* -------------------------------- /* --------------------------------
...@@ -62,7 +64,19 @@ StartupProcTriggerHandler(SIGNAL_ARGS) ...@@ -62,7 +64,19 @@ StartupProcTriggerHandler(SIGNAL_ARGS)
int save_errno = errno; int save_errno = errno;
promote_signaled = true; promote_signaled = true;
SetLatch(MyLatch); WakeupRecovery();
errno = save_errno;
}
/* SIGHUP: set flag to re-read config file at next convenient time */
static void
StartupProcSigHupHandler(SIGNAL_ARGS)
{
int save_errno = errno;
got_SIGHUP = true;
WakeupRecovery();
errno = save_errno; errno = save_errno;
} }
...@@ -77,7 +91,7 @@ StartupProcShutdownHandler(SIGNAL_ARGS) ...@@ -77,7 +91,7 @@ StartupProcShutdownHandler(SIGNAL_ARGS)
proc_exit(1); proc_exit(1);
else else
shutdown_requested = true; shutdown_requested = true;
SetLatch(MyLatch); WakeupRecovery();
errno = save_errno; errno = save_errno;
} }
...@@ -123,9 +137,9 @@ HandleStartupProcInterrupts(void) ...@@ -123,9 +137,9 @@ HandleStartupProcInterrupts(void)
/* /*
* Process any requests or signals received recently. * Process any requests or signals received recently.
*/ */
if (ConfigReloadPending) if (got_SIGHUP)
{ {
ConfigReloadPending = false; got_SIGHUP = false;
StartupRereadConfig(); StartupRereadConfig();
} }
...@@ -158,7 +172,7 @@ StartupProcessMain(void) ...@@ -158,7 +172,7 @@ StartupProcessMain(void)
/* /*
* Properly accept or ignore signals the postmaster might send us. * Properly accept or ignore signals the postmaster might send us.
*/ */
pqsignal(SIGHUP, SignalHandlerForConfigReload); /* reload config file */ pqsignal(SIGHUP, StartupProcSigHupHandler); /* reload config file */
pqsignal(SIGINT, SIG_IGN); /* ignore query cancel */ pqsignal(SIGINT, SIG_IGN); /* ignore query cancel */
pqsignal(SIGTERM, StartupProcShutdownHandler); /* request shutdown */ pqsignal(SIGTERM, StartupProcShutdownHandler); /* request shutdown */
/* SIGQUIT handler was already set up by InitPostmasterChild */ /* SIGQUIT handler was already set up by InitPostmasterChild */
......
...@@ -519,7 +519,14 @@ ResolveRecoveryConflictWithBufferPin(void) ...@@ -519,7 +519,14 @@ ResolveRecoveryConflictWithBufferPin(void)
enable_timeouts(timeouts, 2); enable_timeouts(timeouts, 2);
} }
/* Wait to be signaled by UnpinBuffer() */ /*
* Wait to be signaled by UnpinBuffer().
*
* We assume that only UnpinBuffer() and the timeout requests established
* above can wake us up here. WakeupRecovery() called by walreceiver or
* SIGHUP signal handler, etc cannot do that because it uses the different
* latch from that ProcWaitForSignal() waits on.
*/
ProcWaitForSignal(PG_WAIT_BUFFER_PIN); ProcWaitForSignal(PG_WAIT_BUFFER_PIN);
/* /*
......
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