/* * Cancel any pending wait for lock, when aborting a transaction, and revert * any strong lock count acquisition for a lock being acquired. * * (Normally, this would only happen if we accept a cancel/die * interrupt while waiting; but an ereport(ERROR) before or during the lock * wait is within the realm of possibility, too.) */ void LockErrorCleanup(void) { LWLock *partitionLock; DisableTimeoutParams timeouts[2]; HOLD_INTERRUPTS(); AbortStrongLockAcquire(); /* Nothing to do if we weren't waiting for a lock */ if (lockAwaited == NULL) { RESUME_INTERRUPTS(); return; } /* * Turn off the deadlock and lock timeout timers, if they are still * running (see ProcSleep). Note we must preserve the LOCK_TIMEOUT * indicator flag, since this function is executed before * ProcessInterrupts when responding to SIGINT; else we'd lose the * knowledge that the SIGINT came from a lock timeout and not an external * source. */ timeouts[0].id = DEADLOCK_TIMEOUT; timeouts[0].keep_indicator = false; timeouts[1].id = LOCK_TIMEOUT; timeouts[1].keep_indicator = true; disable_timeouts(timeouts, 2); /* Unlink myself from the wait queue, if on it (might not be anymore!) */ partitionLock = LockHashPartitionLock(lockAwaited->hashcode); LWLockAcquire(partitionLock, LW_EXCLUSIVE); if (MyProc->links.next != NULL) { /* We could not have been granted the lock yet */ RemoveFromWaitQueue(MyProc, lockAwaited->hashcode); } else { /* * Somebody kicked us off the lock queue already. Perhaps they * granted us the lock, or perhaps they detected a deadlock. If they * did grant us the lock, we'd better remember it in our local lock * table. */ if (MyProc->waitStatus == STATUS_OK) GrantAwaitedLock(); } lockAwaited = NULL; LWLockRelease(partitionLock); RESUME_INTERRUPTS(); }
/* * Cancel any pending wait for lock, when aborting a transaction, and revert * any strong lock count acquisition for a lock being acquired. * * (Normally, this would only happen if we accept a cancel/die * interrupt while waiting; but an ereport(ERROR) before or during the lock * wait is within the realm of possibility, too.) */ void LockErrorCleanup(void) { LWLockId partitionLock; AbortStrongLockAcquire(); /* Nothing to do if we weren't waiting for a lock */ if (lockAwaited == NULL) return; /* Turn off the deadlock timer, if it's still running (see ProcSleep) */ disable_timeout(DEADLOCK_TIMEOUT, false); /* Unlink myself from the wait queue, if on it (might not be anymore!) */ partitionLock = LockHashPartitionLock(lockAwaited->hashcode); LWLockAcquire(partitionLock, LW_EXCLUSIVE); if (MyProc->links.next != NULL) { /* We could not have been granted the lock yet */ RemoveFromWaitQueue(MyProc, lockAwaited->hashcode); } else { /* * Somebody kicked us off the lock queue already. Perhaps they * granted us the lock, or perhaps they detected a deadlock. If they * did grant us the lock, we'd better remember it in our local lock * table. */ if (MyProc->waitStatus == STATUS_OK) GrantAwaitedLock(); } lockAwaited = NULL; LWLockRelease(partitionLock); /* * We used to do PGSemaphoreReset() here to ensure that our proc's wait * semaphore is reset to zero. This prevented a leftover wakeup signal * from remaining in the semaphore if someone else had granted us the lock * we wanted before we were able to remove ourselves from the wait-list. * However, now that ProcSleep loops until waitStatus changes, a leftover * wakeup signal isn't harmful, and it seems not worth expending cycles to * get rid of a signal that most likely isn't there. */ }