Fix WakeupWaiters() to not wake up an exclusive locker unnecessarily.
authorHeikki Linnakangas
Mon, 10 Feb 2014 13:14:07 +0000 (15:14 +0200)
committerHeikki Linnakangas
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);