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 68811f1f217..b185c1b5eb6 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -2909,6 +2909,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
@@ -2929,17 +2932,29 @@ 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)
{
- (void) get_timeout_indicator(STATEMENT_TIMEOUT, true);
LockErrorCleanup();
ereport(ERROR,
(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
errmsg("canceling statement due to lock timeout")));
}
- if (get_timeout_indicator(STATEMENT_TIMEOUT, true))
+ if (stmt_timeout_occurred)
{
LockErrorCleanup();
ereport(ERROR,