Skip to content

Commit 82170c7

Browse files
committed
Fix (some of the) breakage introduced into query-cancel processing by HS.
It is absolutely not okay to throw an ereport(ERROR) in any random place in the code just because DoingCommandRead is set; interrupting, say, OpenSSL in the midst of its activities is guaranteed to result in heartache. Instead of that, undo the original optimizations that threw away QueryCancelPending anytime we were starting or finishing a command read, and instead discard the cancel request within ProcessInterrupts if we find that there is no HS reason for forcing a cancel and we are DoingCommandRead. In passing, may I once again condemn the practice of changing the code and not fixing the adjacent comment that you just turned into a lie?
1 parent 6fb7911 commit 82170c7

File tree

1 file changed

+60
-37
lines changed

1 file changed

+60
-37
lines changed

src/backend/tcop/postgres.c

Lines changed: 60 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.580 2010/01/02 16:57:52 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.581 2010/01/07 16:29:58 tgl Exp $
1212
*
1313
* NOTES
1414
* this is the "main" module of the postgres backend and
@@ -476,11 +476,10 @@ prepare_for_client_read(void)
476476
EnableNotifyInterrupt();
477477
EnableCatchupInterrupt();
478478

479-
/* Allow "die" interrupt to be processed while waiting */
479+
/* Allow cancel/die interrupts to be processed while waiting */
480480
ImmediateInterruptOK = true;
481481

482482
/* And don't forget to detect one that already arrived */
483-
QueryCancelPending = false;
484483
CHECK_FOR_INTERRUPTS();
485484
}
486485
}
@@ -494,7 +493,6 @@ client_read_ended(void)
494493
if (DoingCommandRead)
495494
{
496495
ImmediateInterruptOK = false;
497-
QueryCancelPending = false; /* forget any CANCEL signal */
498496

499497
DisableNotifyInterrupt();
500498
DisableCatchupInterrupt();
@@ -2640,12 +2638,11 @@ StatementCancelHandler(SIGNAL_ARGS)
26402638
QueryCancelPending = true;
26412639

26422640
/*
2643-
* If it's safe to interrupt, and we're waiting for a lock, service
2644-
* the interrupt immediately. No point in interrupting if we're
2645-
* waiting for input, however.
2641+
* If it's safe to interrupt, and we're waiting for input or a lock,
2642+
* service the interrupt immediately
26462643
*/
2647-
if (InterruptHoldoffCount == 0 && CritSectionCount == 0 &&
2648-
(DoingCommandRead || ImmediateInterruptOK))
2644+
if (ImmediateInterruptOK && InterruptHoldoffCount == 0 &&
2645+
CritSectionCount == 0)
26492646
{
26502647
/* bump holdoff count to make ProcessInterrupts() a no-op */
26512648
/* until we are done getting ready for it */
@@ -2717,25 +2714,36 @@ ProcessInterrupts(void)
27172714
if (QueryCancelPending)
27182715
{
27192716
QueryCancelPending = false;
2720-
ImmediateInterruptOK = false; /* not idle anymore */
2721-
DisableNotifyInterrupt();
2722-
DisableCatchupInterrupt();
2723-
/* As in quickdie, don't risk sending to client during auth */
2724-
if (ClientAuthInProgress && whereToSendOutput == DestRemote)
2725-
whereToSendOutput = DestNone;
27262717
if (ClientAuthInProgress)
2718+
{
2719+
ImmediateInterruptOK = false; /* not idle anymore */
2720+
DisableNotifyInterrupt();
2721+
DisableCatchupInterrupt();
2722+
/* As in quickdie, don't risk sending to client during auth */
2723+
if (whereToSendOutput == DestRemote)
2724+
whereToSendOutput = DestNone;
27272725
ereport(ERROR,
27282726
(errcode(ERRCODE_QUERY_CANCELED),
27292727
errmsg("canceling authentication due to timeout")));
2730-
else if (cancel_from_timeout)
2728+
}
2729+
if (cancel_from_timeout)
2730+
{
2731+
ImmediateInterruptOK = false; /* not idle anymore */
2732+
DisableNotifyInterrupt();
2733+
DisableCatchupInterrupt();
27312734
ereport(ERROR,
27322735
(errcode(ERRCODE_QUERY_CANCELED),
27332736
errmsg("canceling statement due to statement timeout")));
2734-
else if (IsAutoVacuumWorkerProcess())
2737+
}
2738+
if (IsAutoVacuumWorkerProcess())
2739+
{
2740+
ImmediateInterruptOK = false; /* not idle anymore */
2741+
DisableNotifyInterrupt();
2742+
DisableCatchupInterrupt();
27352743
ereport(ERROR,
27362744
(errcode(ERRCODE_QUERY_CANCELED),
27372745
errmsg("canceling autovacuum task")));
2738-
else
2746+
}
27392747
{
27402748
int cancelMode = MyProc->recoveryConflictMode;
27412749

@@ -2756,34 +2764,50 @@ ProcessInterrupts(void)
27562764
switch (cancelMode)
27572765
{
27582766
case CONFLICT_MODE_FATAL:
2759-
Assert(RecoveryInProgress());
2760-
ereport(FATAL,
2767+
ImmediateInterruptOK = false; /* not idle anymore */
2768+
DisableNotifyInterrupt();
2769+
DisableCatchupInterrupt();
2770+
Assert(RecoveryInProgress());
2771+
ereport(FATAL,
27612772
(errcode(ERRCODE_QUERY_CANCELED),
27622773
errmsg("canceling session due to conflict with recovery")));
27632774

27642775
case CONFLICT_MODE_ERROR:
2765-
/*
2766-
* We are aborting because we need to release
2767-
* locks. So we need to abort out of all
2768-
* subtransactions to make sure we release
2769-
* all locks at whatever their level.
2770-
*
2771-
* XXX Should we try to examine the
2772-
* transaction tree and cancel just enough
2773-
* subxacts to remove locks? Doubt it.
2774-
*/
2775-
Assert(RecoveryInProgress());
2776-
AbortOutOfAnyTransaction();
2777-
ereport(ERROR,
2776+
/*
2777+
* We are aborting because we need to release
2778+
* locks. So we need to abort out of all
2779+
* subtransactions to make sure we release
2780+
* all locks at whatever their level.
2781+
*
2782+
* XXX Should we try to examine the
2783+
* transaction tree and cancel just enough
2784+
* subxacts to remove locks? Doubt it.
2785+
*/
2786+
ImmediateInterruptOK = false; /* not idle anymore */
2787+
DisableNotifyInterrupt();
2788+
DisableCatchupInterrupt();
2789+
Assert(RecoveryInProgress());
2790+
AbortOutOfAnyTransaction();
2791+
ereport(ERROR,
27782792
(errcode(ERRCODE_QUERY_CANCELED),
27792793
errmsg("canceling statement due to conflict with recovery")));
2780-
return;
27812794

27822795
default:
2783-
/* No conflict pending, so fall through */
2784-
break;
2796+
/* No conflict pending, so fall through */
2797+
break;
27852798
}
2799+
}
27862800

2801+
/*
2802+
* If we are reading a command from the client, just ignore the
2803+
* cancel request --- sending an extra error message won't
2804+
* accomplish anything. Otherwise, go ahead and throw the error.
2805+
*/
2806+
if (!DoingCommandRead)
2807+
{
2808+
ImmediateInterruptOK = false; /* not idle anymore */
2809+
DisableNotifyInterrupt();
2810+
DisableCatchupInterrupt();
27872811
ereport(ERROR,
27882812
(errcode(ERRCODE_QUERY_CANCELED),
27892813
errmsg("canceling statement due to user request")));
@@ -3626,7 +3650,6 @@ PostgresMain(int argc, char *argv[], const char *username)
36263650
* conditional since we don't want, say, reads on behalf of COPY FROM
36273651
* STDIN doing the same thing.)
36283652
*/
3629-
QueryCancelPending = false; /* forget any earlier CANCEL signal */
36303653
DoingCommandRead = true;
36313654

36323655
/*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy