aboutsummaryrefslogtreecommitdiff
path: root/src/backend/tcop/postgres.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r--src/backend/tcop/postgres.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index c97842e2aee..0ad9221f56c 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -2910,6 +2910,9 @@ ProcessInterrupts(void)
if (QueryCancelPending)
{
+ bool lock_timeout_occurred;
+ bool stmt_timeout_occurred;
+
/*
* Don't allow query cancel interrupts while reading input from the
* client, because we might lose sync in the FE/BE protocol. (Die
@@ -2943,12 +2946,24 @@ ProcessInterrupts(void)
/*
* If LOCK_TIMEOUT and STATEMENT_TIMEOUT indicators are both set, we
- * prefer to report the former; but be sure to clear both.
+ * need to clear both, so always fetch both.
*/
- if (get_timeout_indicator(LOCK_TIMEOUT, true))
+ lock_timeout_occurred = get_timeout_indicator(LOCK_TIMEOUT, true);
+ stmt_timeout_occurred = get_timeout_indicator(STATEMENT_TIMEOUT, true);
+
+ /*
+ * If both were set, we want to report whichever timeout completed
+ * earlier; this ensures consistent behavior if the machine is slow
+ * enough that the second timeout triggers before we get here. A tie
+ * is arbitrarily broken in favor of reporting a lock timeout.
+ */
+ if (lock_timeout_occurred && stmt_timeout_occurred &&
+ get_timeout_finish_time(STATEMENT_TIMEOUT) < get_timeout_finish_time(LOCK_TIMEOUT))
+ lock_timeout_occurred = false; /* report stmt timeout */
+
+ if (lock_timeout_occurred)
{
ImmediateInterruptOK = false; /* not idle anymore */
- (void) get_timeout_indicator(STATEMENT_TIMEOUT, true);
LockErrorCleanup();
DisableNotifyInterrupt();
DisableCatchupInterrupt();
@@ -2956,7 +2971,7 @@ ProcessInterrupts(void)
(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
errmsg("canceling statement due to lock timeout")));
}
- if (get_timeout_indicator(STATEMENT_TIMEOUT, true))
+ if (stmt_timeout_occurred)
{
ImmediateInterruptOK = false; /* not idle anymore */
LockErrorCleanup();