]> granicus.if.org Git - postgresql/commitdiff
Fix WakeupWaiters() to not wake up an exclusive locker unnecessarily.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 10 Feb 2014 13:14:07 +0000 (15:14 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 10 Feb 2014 13:18:18 +0000 (15:18 +0200)
WakeupWaiters() is supposed to wake up all LW_WAIT_UNTIL_FREE waiters of
the slot, but the loop incorrectly also woke up the first LW_EXCLUSIVE
waiter, if there was no LW_WAIT_UNTIL_FREE waiters in the queue.

Noted by Andres Freund. This code is new in 9.4, so no backpatching.

src/backend/access/transam/xlog.c

index 7f63185b1cc10998144b0ea28cfdb1bc7ce5e1b1..508970a751dfdfcdf4324355dd4e9dec3d88a035 100644 (file)
@@ -1842,15 +1842,14 @@ WakeupWaiters(XLogRecPtr EndPos)
        slot->xlogInsertingAt = EndPos;
 
        /*
-        * See if there are any waiters that need to be woken up.
+        * See if there are any LW_WAIT_UNTIL_FREE waiters that need to be woken
+        * up. They are always in the front of the queue.
         */
        head = slot->head;
 
-       if (head != NULL)
+       if (head != NULL && head->lwWaitMode == LW_WAIT_UNTIL_FREE)
        {
                proc = head;
-
-               /* LW_WAIT_UNTIL_FREE waiters are always in the front of the queue */
                next = proc->lwWaitLink;
                while (next && next->lwWaitMode == LW_WAIT_UNTIL_FREE)
                {
@@ -1862,6 +1861,8 @@ WakeupWaiters(XLogRecPtr EndPos)
                slot->head = next;
                proc->lwWaitLink = NULL;
        }
+       else
+               head = NULL;
 
        /* We are done updating shared state of the lock itself. */
        SpinLockRelease(&slot->mutex);