]> granicus.if.org Git - postgresql/commitdiff
Fix deadlock with LWLockAcquireWithVar and LWLockWaitForVar.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Tue, 14 Oct 2014 06:55:26 +0000 (09:55 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Tue, 14 Oct 2014 07:06:47 +0000 (10:06 +0300)
LWLockRelease should release all backends waiting with LWLockWaitForVar,
even when another backend has already been woken up to acquire the lock,
i.e. when releaseOK is false. LWLockWaitForVar can return as soon as the
protected value changes, even if the other backend will acquire the lock.
Fix that by resetting releaseOK to true in LWLockWaitForVar, whenever
adding itself to the wait queue.

This should fix the bug reported by MauMau, where the system occasionally
hangs when there is a lot of concurrent WAL activity and a checkpoint.
Backpatch to 9.4, where this code was added.

src/backend/storage/lmgr/lwlock.c

index 9fe6855945bb56d105a4d7896729c15958ef6087..bcec17335b8f70831204a2b9a4301b3112ea9f00 100644 (file)
@@ -1005,6 +1005,12 @@ LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval)
                        lock->tail = proc;
                lock->head = proc;
 
+               /*
+                * Set releaseOK, to make sure we get woken up as soon as the lock is
+                * released.
+                */
+               lock->releaseOK = true;
+
                /* Can release the mutex now */
                SpinLockRelease(&lock->mutex);