summaryrefslogtreecommitdiff
path: root/src/backend/storage/lmgr/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/lmgr/proc.c')
-rw-r--r--src/backend/storage/lmgr/proc.c50
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