From f260f9e275effca846361f213e0f08c3865394b0 Mon Sep 17 00:00:00 2001 From: Matthias van de Meent Date: Thu, 18 Jun 2026 17:06:55 +0200 Subject: [PATCH v3] IPC/standby: keep better track of taken locks Previously, a lock that wasn't taken (e.g. due to a lack of available locks) could cause all kinds of havoc in recovery-local lock state. Now, we're more robust against that, by only registering the relation lock once the lock is taken: If LockAcquire() fails, the failed lock won't be present in the xidentry's list. --- src/backend/storage/ipc/standby.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c index 872679ca447..0ba78bf63d6 100644 --- a/src/backend/storage/ipc/standby.c +++ b/src/backend/storage/ipc/standby.c @@ -1016,14 +1016,20 @@ StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid) lockentry = hash_search(RecoveryLockHash, &key, HASH_ENTER, &found); if (!found) { - /* It's new, so link it into the XID's list ... */ - lockentry->next = xidentry->head; - xidentry->head = lockentry; - - /* ... and acquire the lock locally. */ + /* First, acquire the lock ... */ SET_LOCKTAG_RELATION(locktag, dbOid, relOid); (void) LockAcquire(&locktag, AccessExclusiveLock, true, false); + + /* + * ... and then, link it into the local state. + * + * This avoids issues in StandbyReleaseXidEntryLocks when LockAcquire + * fails to acquire a lock (e.g. due to lock entry exhaustion); in that + * case the xidentry isn't inconsistent. + */ + lockentry->next = xidentry->head; + xidentry->head = lockentry; } } -- 2.50.1 (Apple Git-155)