@@ -2920,6 +2920,9 @@ ProcessInterrupts(void)
2920
2920
2921
2921
if (QueryCancelPending )
2922
2922
{
2923
+ bool lock_timeout_occurred ;
2924
+ bool stmt_timeout_occurred ;
2925
+
2923
2926
/*
2924
2927
* Don't allow query cancel interrupts while reading input from the
2925
2928
* client, because we might lose sync in the FE/BE protocol. (Die
@@ -2940,17 +2943,29 @@ ProcessInterrupts(void)
2940
2943
2941
2944
/*
2942
2945
* If LOCK_TIMEOUT and STATEMENT_TIMEOUT indicators are both set, we
2943
- * prefer to report the former; but be sure to clear both.
2946
+ * need to clear both, so always fetch both.
2944
2947
*/
2945
- if (get_timeout_indicator (LOCK_TIMEOUT , true))
2948
+ lock_timeout_occurred = get_timeout_indicator (LOCK_TIMEOUT , true);
2949
+ stmt_timeout_occurred = get_timeout_indicator (STATEMENT_TIMEOUT , true);
2950
+
2951
+ /*
2952
+ * If both were set, we want to report whichever timeout completed
2953
+ * earlier; this ensures consistent behavior if the machine is slow
2954
+ * enough that the second timeout triggers before we get here. A tie
2955
+ * is arbitrarily broken in favor of reporting a lock timeout.
2956
+ */
2957
+ if (lock_timeout_occurred && stmt_timeout_occurred &&
2958
+ get_timeout_finish_time (STATEMENT_TIMEOUT ) < get_timeout_finish_time (LOCK_TIMEOUT ))
2959
+ lock_timeout_occurred = false; /* report stmt timeout */
2960
+
2961
+ if (lock_timeout_occurred )
2946
2962
{
2947
- (void ) get_timeout_indicator (STATEMENT_TIMEOUT , true);
2948
2963
LockErrorCleanup ();
2949
2964
ereport (ERROR ,
2950
2965
(errcode (ERRCODE_LOCK_NOT_AVAILABLE ),
2951
2966
errmsg ("canceling statement due to lock timeout" )));
2952
2967
}
2953
- if (get_timeout_indicator ( STATEMENT_TIMEOUT , true) )
2968
+ if (stmt_timeout_occurred )
2954
2969
{
2955
2970
LockErrorCleanup ();
2956
2971
ereport (ERROR ,
0 commit comments