From 58239700edf0c669f4807da6140a595c2a1e8a5e Mon Sep 17 00:00:00 2001 From: JoongHyuk Shin Date: Fri, 17 Apr 2026 16:58:31 +0900 Subject: [PATCH] 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. Also remove the XXX comment that noted this problem. --- src/backend/storage/ipc/standby.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c index 29af7733948..9744db5715c 100644 --- a/src/backend/storage/ipc/standby.c +++ b/src/backend/storage/ipc/standby.c @@ -851,17 +851,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