public inbox for [email protected]  
help / color / mirror / Atom feed
From: SATYANARAYANA NARLAPURAM <[email protected]>
To: PostgreSQL Hackers <[email protected]>
Subject: LockHasWaiters() crashes on fast-path locks
Date: Wed, 25 Mar 2026 14:15:08 -0700
Message-ID: <CAHg+QDe_=ZahnRx37bzrqYenKn_S5YDQ00fTfwe-ZUmjqO=qLg@mail.gmail.com> (raw)

Hi Hackers,

LockHasWaiters() assumes that the LOCALLOCK's lock and proclock pointers
are populated, but this is not the case for locks acquired via the
fast-path optimization. Weak locks (< ShareUpdateExclusiveLock) on
relations may not be stored in the shared lock hash table, and the
LOCALLOCK entry is left with lock = NULL and proclock = NULL in such a case.

If LockHasWaiters() is called for such a lock, it dereferences those NULL
pointers when it reads proclock->holdMask and lock->waitMask, causing a
segfault.

The only existing caller is lazy_truncate_heap() in VACUUM, which queries
LockHasWaitersRelation(rel, AccessExclusiveLock). Since AccessExclusiveLock
is the strongest lock level, it is never fast-pathed, so the bug has never
been triggered in practice. However, any new caller that passes a weak lock
mode, for example, checking whether a DDL is waiting on an AccessShareLock
will crash. The fix is to transfer the lock to the main lock table before
we access them.

Attached a patch to address this issue.


Thanks,
Satya


Attachments:

  [application/octet-stream] 0001-lock-has-waiters-fast-path-fix.patch (829B, 3-0001-lock-has-waiters-fast-path-fix.patch)
  download | inline diff:
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index d930c66c..ff9b9caa 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -743,6 +743,20 @@ LockHasWaiters(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
 	 */
 	partitionLock = LockHashPartitionLock(locallock->hashcode);
 
+	/*
+	 * If the lock was acquired via the fast path, locallock->lock and
+	 * locallock->proclock will be NULL.  We must transfer the lock to the
+	 * main lock table before we can inspect LOCK->waitMask.
+	 */
+	if (locallock->lock == NULL)
+	{
+		PROCLOCK   *fp_proclock;
+
+		fp_proclock = FastPathGetRelationLockEntry(locallock);
+		locallock->lock = fp_proclock->tag.myLock;
+		locallock->proclock = fp_proclock;
+	}
+
 	LWLockAcquire(partitionLock, LW_SHARED);
 
 	/*


view thread (5+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected]
  Subject: Re: LockHasWaiters() crashes on fast-path locks
  In-Reply-To: <CAHg+QDe_=ZahnRx37bzrqYenKn_S5YDQ00fTfwe-ZUmjqO=qLg@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox