v1-0001-Set-1s-WaitLatch-timeout-if-standby-limit-has-exp.patch
application/octet-stream
Filename: v1-0001-Set-1s-WaitLatch-timeout-if-standby-limit-has-exp.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v1-0001
Subject: Set 1s WaitLatch timeout if standby limit has expired in ResolveRecoveryConflictWithBufferPin
| File | + | − |
|---|---|---|
| src/backend/storage/ipc/standby.c | 10 | 6 |
| src/backend/storage/lmgr/proc.c | 16 | 3 |
| src/include/storage/proc.h | 2 | 0 |
From 5b4994cc6c244ecc6eb6826f91a35cbd07a9f00e Mon Sep 17 00:00:00 2001
From: Anthony Hsu <erwaman@gmail.com>
Date: Sun, 6 Jul 2025 11:20:50 -0700
Subject: [PATCH v1] Set 1s WaitLatch timeout if standby limit has expired in
ResolveRecoveryConflictWithBufferPin
---
src/backend/storage/ipc/standby.c | 16 ++++++++++------
src/backend/storage/lmgr/proc.c | 19 ++++++++++++++++---
src/include/storage/proc.h | 2 ++
3 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c
index 7fa8d9247e0..ff9070aba35 100644
--- a/src/backend/storage/ipc/standby.c
+++ b/src/backend/storage/ipc/standby.c
@@ -793,12 +793,14 @@ void
ResolveRecoveryConflictWithBufferPin(void)
{
TimestampTz ltime;
+ bool standby_limit_expired;
Assert(InHotStandby);
ltime = GetStandbyLimitTime();
+ standby_limit_expired = GetCurrentTimestamp() >= ltime && ltime != 0;
- if (GetCurrentTimestamp() >= ltime && ltime != 0)
+ if (standby_limit_expired)
{
/*
* We're already behind, so clear a path as quickly as possible.
@@ -835,12 +837,14 @@ ResolveRecoveryConflictWithBufferPin(void)
* Wait to be signaled by UnpinBuffer() or for the wait to be interrupted
* by one of the timeouts established above.
*
- * 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.
+ * If the standby limit has already expired, we also set a 1s timeout. This
+ * is to ensure the startup process is still woken up in a reasonable time
+ * in case a new backend sneaks in and acquires a conflicting pin before the
+ * original conflicting backends are able to cancel themselves and reduce
+ * the pin count to 1 (which wakes up the startup process).
*/
- ProcWaitForSignal(WAIT_EVENT_BUFFER_PIN);
+ ProcWaitForSignalWithTimeout(WAIT_EVENT_BUFFER_PIN,
+ standby_limit_expired ? 1000 : 0);
if (got_standby_delay_timeout)
SendRecoveryConflictWithBufferPin(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN);
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index e9ef0fbfe32..7114256e9ed 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -1965,16 +1965,29 @@ GetLockHoldersAndWaiters(LOCALLOCK *locallock, StringInfo lock_holders_sbuf,
/*
* ProcWaitForSignal - wait for a signal from another backend.
+ */
+void
+ProcWaitForSignal(uint32 wait_event_info)
+{
+ ProcWaitForSignalWithTimeout(wait_event_info, 0);
+}
+
+/*
+ * ProcWaitForSignalWithTimeout - wait for a signal from another backend with a
+ * timeout.
*
* As this uses the generic process latch the caller has to be robust against
* unrelated wakeups: Always check that the desired state has occurred, and
* wait again if not.
*/
void
-ProcWaitForSignal(uint32 wait_event_info)
+ProcWaitForSignalWithTimeout(uint32 wait_event_info, long timeout_ms)
{
- (void) WaitLatch(MyLatch, WL_LATCH_SET | WL_EXIT_ON_PM_DEATH, 0,
- wait_event_info);
+ int wake_events = WL_LATCH_SET | WL_EXIT_ON_PM_DEATH;
+ if (timeout_ms > 0)
+ wake_events |= WL_TIMEOUT;
+
+ (void) WaitLatch(MyLatch, wake_events, timeout_ms, wait_event_info);
ResetLatch(MyLatch);
CHECK_FOR_INTERRUPTS();
}
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 9f9b3fcfbf1..930510ca8e5 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -505,6 +505,8 @@ extern void GetLockHoldersAndWaiters(LOCALLOCK *locallock,
int *lockHoldersNum);
extern void ProcWaitForSignal(uint32 wait_event_info);
+extern void ProcWaitForSignalWithTimeout(uint32 wait_event_info,
+ long timeout_ms);
extern void ProcSendSignal(ProcNumber procNumber);
extern PGPROC *AuxiliaryPidGetProc(int pid);
--
2.50.0.727.gbf7dc18ff4-goog