From e70a2fc74a63d4c1e3d1277e27a37b1e26710fff Mon Sep 17 00:00:00 2001 From: JoongHyuk Shin Date: Fri, 17 Apr 2026 16:58:31 +0900 Subject: [PATCH v2] Prevent repeated deadlock-check signals in standby buffer pin waits After sending RECOVERY_CONFLICT_BUFFERPIN_DEADLOCK, the startup process returned without waiting, so the caller's loop would fire another deadlock_timeout and re-send the signal every interval. This added unnecessary overhead in both the startup process and backends. Fix by adding a ProcWaitForSignal() call after the deadlock-check signal, mirroring the approach already used in the lock-conflict path (commit 8900b5a9d59a). This ensures the signal is sent at most once per deadlock_timeout period rather than repeatedly. Additionally, reset got_standby_delay_timeout to false before enabling STANDBY_TIMEOUT, for symmetry with the existing got_standby_deadlock_timeout reset. Remove the XXX comment that noted this problem. --- src/backend/storage/ipc/standby.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c index 29af7733948..0dba1fb4289 100644 --- a/src/backend/storage/ipc/standby.c +++ b/src/backend/storage/ipc/standby.c @@ -818,6 +818,7 @@ ResolveRecoveryConflictWithBufferPin(void) if (ltime != 0) { + got_standby_delay_timeout = false; timeouts[cnt].id = STANDBY_TIMEOUT; timeouts[cnt].type = TMPARAM_AT; timeouts[cnt].fin_time = ltime; @@ -851,17 +852,19 @@ ResolveRecoveryConflictWithBufferPin(void) /* * Send out a request for hot-standby backends to check themselves for * deadlocks. - * - * XXX The subsequent ResolveRecoveryConflictWithBufferPin() will wait - * to be signaled by UnpinBuffer() again and send a request for - * deadlocks check if deadlock_timeout happens. This causes the - * request to continue to be sent every deadlock_timeout until the - * buffer is unpinned or ltime is reached. This would increase the - * workload in the startup process and backends. In practice it may - * not be so harmful because the period that the buffer is kept pinned - * is basically no so long. But we should fix this? */ SendRecoveryConflictWithBufferPin(RECOVERY_CONFLICT_BUFFERPIN_DEADLOCK); + + /* + * Wait here to be signaled by UnpinBuffer(), to prevent the + * subsequent ResolveRecoveryConflictWithBufferPin() call (from the + * caller's loop) from firing another deadlock_timeout and re-sending + * the deadlock-check signal. Without this, the signal would be sent + * every deadlock_timeout interval until the buffer is unpinned or + * ltime is reached. + */ + got_standby_deadlock_timeout = false; + ProcWaitForSignal(WAIT_EVENT_BUFFER_CLEANUP); } /* -- 2.52.0