We have a wait-pin-to-1 mechanism in LockBufferForCleanup() like this:

    1:  bufHdr->wait_backend_pid = MyProcPid;
    2:  bufHdr->flags |= BM_PIN_COUNT_WAITER;
    3:  PinCountWaitBuf = bufHdr;
    4:  UnlockBufHdr_NoHoldoff(bufHdr);
    5:  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
    6:  /* Wait to be signaled by UnpinBuffer() */
    7:  ProcWaitForSignal();

Say if the waiter encounters an error on line 5 or gets a cancel signal on
line 6, it will abort current transaction and call UnlockBuffers() to cancel
the wait. However, a possible execution sequence involving another process
doing UnpinBuffer() may look like this:

unpinner: lockHdr(); read and reset flag; unlockHdr();
waiter:  lockHdr(); reset flag; unlockHdr(); ProcCancelWaitForSignal();
unpinner: ProcSendSignal();

After this, the proc->sem will be bumped to 1 unexpectedly ... Since this
problem is rare, a possible fix is to put a critical section around line 1
to 7 and remove UnlockBuffers() accordingly.

Regards,
Qingqing









---------------------------(end of broadcast)---------------------------
TIP 4: Have you searched our list archives?

               http://archives.postgresql.org

Reply via email to