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
byUnpinBuffer() */ 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