diff options
Diffstat (limited to 'src/backend/storage/lmgr/proc.c')
-rw-r--r-- | src/backend/storage/lmgr/proc.c | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 2e012fad11f..5809a797986 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -55,6 +55,7 @@ /* GUC variables */ int DeadlockTimeout = 1000; int StatementTimeout = 0; +int LockTimeout = 0; bool log_lock_waits = false; /* Pointer to this process's PGPROC and PGXACT structs, if any */ @@ -665,6 +666,7 @@ void LockErrorCleanup(void) { LWLockId partitionLock; + DisableTimeoutParams timeouts[2]; AbortStrongLockAcquire(); @@ -672,8 +674,19 @@ LockErrorCleanup(void) if (lockAwaited == NULL) return; - /* Turn off the deadlock timer, if it's still running (see ProcSleep) */ - disable_timeout(DEADLOCK_TIMEOUT, false); + /* + * 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); @@ -1072,8 +1085,24 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) * * By delaying the check until we've waited for a bit, we can avoid * running the rather expensive deadlock-check code in most cases. + * + * If LockTimeout is set, also enable the timeout for that. We can save a + * few cycles by enabling both timeout sources in one call. */ - enable_timeout_after(DEADLOCK_TIMEOUT, DeadlockTimeout); + if (LockTimeout > 0) + { + EnableTimeoutParams timeouts[2]; + + timeouts[0].id = DEADLOCK_TIMEOUT; + timeouts[0].type = TMPARAM_AFTER; + timeouts[0].delay_ms = DeadlockTimeout; + timeouts[1].id = LOCK_TIMEOUT; + timeouts[1].type = TMPARAM_AFTER; + timeouts[1].delay_ms = LockTimeout; + enable_timeouts(timeouts, 2); + } + else + enable_timeout_after(DEADLOCK_TIMEOUT, DeadlockTimeout); /* * If someone wakes us between LWLockRelease and PGSemaphoreLock, @@ -1240,9 +1269,20 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) } while (myWaitStatus == STATUS_WAITING); /* - * Disable the timer, if it's still running + * Disable the timers, if they are still running */ - disable_timeout(DEADLOCK_TIMEOUT, false); + if (LockTimeout > 0) + { + DisableTimeoutParams timeouts[2]; + + timeouts[0].id = DEADLOCK_TIMEOUT; + timeouts[0].keep_indicator = false; + timeouts[1].id = LOCK_TIMEOUT; + timeouts[1].keep_indicator = false; + disable_timeouts(timeouts, 2); + } + else + disable_timeout(DEADLOCK_TIMEOUT, false); /* * Re-acquire the lock table's partition lock. We have to do this to hold |