Skip to content

Commit d47cfef

Browse files
committed
Move interrupt checking from ExecProcNode() to executor nodes.
In a followup commit ExecProcNode(), and especially the large switch it contains, will largely be replaced by a function pointer directly to the correct node. The node functions will then get invoked by a thin inline function wrapper. To avoid having to include miscadmin.h in headers - CHECK_FOR_INTERRUPTS() - move the interrupt checks into the individual executor routines. While looking through all executor nodes, I noticed a number of arguably missing interrupt checks, add these too. Author: Andres Freund, Tom Lane Reviewed-By: Tom Lane Discussion: https://postgr.es/m/22833.1490390175@sss.pgh.pa.us
1 parent 9dea962 commit d47cfef

29 files changed

+104
-10
lines changed

src/backend/executor/execProcnode.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -399,8 +399,6 @@ ExecProcNode(PlanState *node)
399399
{
400400
TupleTableSlot *result;
401401

402-
CHECK_FOR_INTERRUPTS();
403-
404402
if (node->chgParam != NULL) /* something changed */
405403
ExecReScan(node); /* let ReScan handle this */
406404

src/backend/executor/nodeAgg.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,8 @@ fetch_input_tuple(AggState *aggstate)
677677

678678
if (aggstate->sort_in)
679679
{
680+
/* make sure we check for interrupts in either path through here */
681+
CHECK_FOR_INTERRUPTS();
680682
if (!tuplesort_gettupleslot(aggstate->sort_in, true, false,
681683
aggstate->sort_slot, NULL))
682684
return NULL;
@@ -1414,6 +1416,8 @@ process_ordered_aggregate_multi(AggState *aggstate,
14141416
while (tuplesort_gettupleslot(pertrans->sortstates[aggstate->current_set],
14151417
true, true, slot1, &newAbbrevVal))
14161418
{
1419+
CHECK_FOR_INTERRUPTS();
1420+
14171421
/*
14181422
* Extract the first numTransInputs columns as datums to pass to the
14191423
* transfn. (This will help execTuplesMatch too, so we do it
@@ -2100,6 +2104,8 @@ ExecAgg(AggState *node)
21002104
{
21012105
TupleTableSlot *result = NULL;
21022106

2107+
CHECK_FOR_INTERRUPTS();
2108+
21032109
if (!node->agg_done)
21042110
{
21052111
/* Dispatch based on strategy */
@@ -2563,6 +2569,8 @@ agg_retrieve_hash_table(AggState *aggstate)
25632569
TupleTableSlot *hashslot = perhash->hashslot;
25642570
int i;
25652571

2572+
CHECK_FOR_INTERRUPTS();
2573+
25662574
/*
25672575
* Find the next entry in the hash table
25682576
*/

src/backend/executor/nodeAppend.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959

6060
#include "executor/execdebug.h"
6161
#include "executor/nodeAppend.h"
62+
#include "miscadmin.h"
6263

6364
static bool exec_append_initialize_next(AppendState *appendstate);
6465

@@ -204,6 +205,8 @@ ExecAppend(AppendState *node)
204205
PlanState *subnode;
205206
TupleTableSlot *result;
206207

208+
CHECK_FOR_INTERRUPTS();
209+
207210
/*
208211
* figure out which subplan we are currently processing
209212
*/

src/backend/executor/nodeBitmapHeapscan.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "access/transam.h"
4242
#include "executor/execdebug.h"
4343
#include "executor/nodeBitmapHeapscan.h"
44+
#include "miscadmin.h"
4445
#include "pgstat.h"
4546
#include "storage/bufmgr.h"
4647
#include "storage/predicate.h"
@@ -192,6 +193,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
192193
Page dp;
193194
ItemId lp;
194195

196+
CHECK_FOR_INTERRUPTS();
197+
195198
/*
196199
* Get next page of results if needed
197200
*/

src/backend/executor/nodeCustom.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "executor/nodeCustom.h"
1616
#include "nodes/execnodes.h"
1717
#include "nodes/plannodes.h"
18+
#include "miscadmin.h"
1819
#include "parser/parsetree.h"
1920
#include "utils/hsearch.h"
2021
#include "utils/memutils.h"
@@ -104,6 +105,8 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
104105
TupleTableSlot *
105106
ExecCustomScan(CustomScanState *node)
106107
{
108+
CHECK_FOR_INTERRUPTS();
109+
107110
Assert(node->methods->ExecCustomScan != NULL);
108111
return node->methods->ExecCustomScan(node);
109112
}

src/backend/executor/nodeGather.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ ExecGather(GatherState *node)
128128
TupleTableSlot *slot;
129129
ExprContext *econtext;
130130

131+
CHECK_FOR_INTERRUPTS();
132+
131133
/*
132134
* Initialize the parallel context and workers on first execution. We do
133135
* this on first execution rather than during node initialization, as it
@@ -247,6 +249,8 @@ gather_getnext(GatherState *gatherstate)
247249

248250
while (gatherstate->reader != NULL || gatherstate->need_to_scan_locally)
249251
{
252+
CHECK_FOR_INTERRUPTS();
253+
250254
if (gatherstate->reader != NULL)
251255
{
252256
MemoryContext oldContext;

src/backend/executor/nodeGatherMerge.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ ExecGatherMerge(GatherMergeState *node)
164164
ExprContext *econtext;
165165
int i;
166166

167+
CHECK_FOR_INTERRUPTS();
168+
167169
/*
168170
* As with Gather, we don't launch workers until this node is actually
169171
* executed.
@@ -393,6 +395,8 @@ gather_merge_init(GatherMergeState *gm_state)
393395
reread:
394396
for (i = 0; i < nreaders + 1; i++)
395397
{
398+
CHECK_FOR_INTERRUPTS();
399+
396400
if (!gm_state->gm_tuple_buffers[i].done &&
397401
(TupIsNull(gm_state->gm_slots[i]) ||
398402
gm_state->gm_slots[i]->tts_isempty))

src/backend/executor/nodeGroup.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include "executor/executor.h"
2626
#include "executor/nodeGroup.h"
27+
#include "miscadmin.h"
2728

2829

2930
/*
@@ -40,6 +41,8 @@ ExecGroup(GroupState *node)
4041
TupleTableSlot *firsttupleslot;
4142
TupleTableSlot *outerslot;
4243

44+
CHECK_FOR_INTERRUPTS();
45+
4346
/*
4447
* get state info from node
4548
*/

src/backend/executor/nodeHash.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,9 @@ ExecHashIncreaseNumBuckets(HashJoinTable hashtable)
810810
idx += MAXALIGN(HJTUPLE_OVERHEAD +
811811
HJTUPLE_MINTUPLE(hashTuple)->t_len);
812812
}
813+
814+
/* allow this loop to be cancellable */
815+
CHECK_FOR_INTERRUPTS();
813816
}
814817
}
815818

@@ -1192,6 +1195,9 @@ ExecScanHashTableForUnmatched(HashJoinState *hjstate, ExprContext *econtext)
11921195

11931196
hashTuple = hashTuple->next;
11941197
}
1198+
1199+
/* allow this loop to be cancellable */
1200+
CHECK_FOR_INTERRUPTS();
11951201
}
11961202

11971203
/*

src/backend/executor/nodeHashjoin.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ ExecHashJoin(HashJoinState *node)
9292
*/
9393
for (;;)
9494
{
95+
/*
96+
* It's possible to iterate this loop many times before returning a
97+
* tuple, in some pathological cases such as needing to move much of
98+
* the current batch to a later batch. So let's check for interrupts
99+
* each time through.
100+
*/
101+
CHECK_FOR_INTERRUPTS();
102+
95103
switch (node->hj_JoinState)
96104
{
97105
case HJ_BUILD_HASHTABLE:
@@ -246,13 +254,6 @@ ExecHashJoin(HashJoinState *node)
246254

247255
case HJ_SCAN_BUCKET:
248256

249-
/*
250-
* We check for interrupts here because this corresponds to
251-
* where we'd fetch a row from a child plan node in other join
252-
* types.
253-
*/
254-
CHECK_FOR_INTERRUPTS();
255-
256257
/*
257258
* Scan the selected hash bucket for matches to current outer
258259
*/

src/backend/executor/nodeIndexonlyscan.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "executor/execdebug.h"
3535
#include "executor/nodeIndexonlyscan.h"
3636
#include "executor/nodeIndexscan.h"
37+
#include "miscadmin.h"
3738
#include "storage/bufmgr.h"
3839
#include "storage/predicate.h"
3940
#include "utils/memutils.h"
@@ -117,6 +118,8 @@ IndexOnlyNext(IndexOnlyScanState *node)
117118
{
118119
HeapTuple tuple = NULL;
119120

121+
CHECK_FOR_INTERRUPTS();
122+
120123
/*
121124
* We can skip the heap fetch if the TID references a heap page on
122125
* which all tuples are known visible to everybody. In any case,

src/backend/executor/nodeIndexscan.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "executor/execdebug.h"
3535
#include "executor/nodeIndexscan.h"
3636
#include "lib/pairingheap.h"
37+
#include "miscadmin.h"
3738
#include "nodes/nodeFuncs.h"
3839
#include "optimizer/clauses.h"
3940
#include "utils/array.h"
@@ -131,6 +132,8 @@ IndexNext(IndexScanState *node)
131132
*/
132133
while ((tuple = index_getnext(scandesc, direction)) != NULL)
133134
{
135+
CHECK_FOR_INTERRUPTS();
136+
134137
/*
135138
* Store the scanned tuple in the scan tuple slot of the scan state.
136139
* Note: we pass 'false' because tuples returned by amgetnext are
@@ -233,6 +236,8 @@ IndexNextWithReorder(IndexScanState *node)
233236

234237
for (;;)
235238
{
239+
CHECK_FOR_INTERRUPTS();
240+
236241
/*
237242
* Check the reorder queue first. If the topmost tuple in the queue
238243
* has an ORDER BY value smaller than (or equal to) the value last
@@ -299,6 +304,8 @@ IndexNextWithReorder(IndexScanState *node)
299304
{
300305
/* Fails recheck, so drop it and loop back for another */
301306
InstrCountFiltered2(node, 1);
307+
/* allow this loop to be cancellable */
308+
CHECK_FOR_INTERRUPTS();
302309
goto next_indextuple;
303310
}
304311
}

src/backend/executor/nodeLimit.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include "executor/executor.h"
2525
#include "executor/nodeLimit.h"
26+
#include "miscadmin.h"
2627
#include "nodes/nodeFuncs.h"
2728

2829
static void recompute_limits(LimitState *node);
@@ -43,6 +44,8 @@ ExecLimit(LimitState *node)
4344
TupleTableSlot *slot;
4445
PlanState *outerPlan;
4546

47+
CHECK_FOR_INTERRUPTS();
48+
4649
/*
4750
* get information from the node
4851
*/

src/backend/executor/nodeLockRows.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "executor/executor.h"
2727
#include "executor/nodeLockRows.h"
2828
#include "foreign/fdwapi.h"
29+
#include "miscadmin.h"
2930
#include "storage/bufmgr.h"
3031
#include "utils/rel.h"
3132
#include "utils/tqual.h"
@@ -44,6 +45,8 @@ ExecLockRows(LockRowsState *node)
4445
bool epq_needed;
4546
ListCell *lc;
4647

48+
CHECK_FOR_INTERRUPTS();
49+
4750
/*
4851
* get information from the node
4952
*/

src/backend/executor/nodeMaterial.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ ExecMaterial(MaterialState *node)
4545
bool eof_tuplestore;
4646
TupleTableSlot *slot;
4747

48+
CHECK_FOR_INTERRUPTS();
49+
4850
/*
4951
* get state info from node
5052
*/

src/backend/executor/nodeMergeAppend.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@
4040

4141
#include "executor/execdebug.h"
4242
#include "executor/nodeMergeAppend.h"
43-
4443
#include "lib/binaryheap.h"
44+
#include "miscadmin.h"
4545

4646
/*
4747
* We have one slot for each item in the heap array. We use SlotNumber
@@ -175,6 +175,8 @@ ExecMergeAppend(MergeAppendState *node)
175175
TupleTableSlot *result;
176176
SlotNumber i;
177177

178+
CHECK_FOR_INTERRUPTS();
179+
178180
if (!node->ms_initialized)
179181
{
180182
/*

src/backend/executor/nodeMergejoin.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
#include "access/nbtree.h"
9696
#include "executor/execdebug.h"
9797
#include "executor/nodeMergejoin.h"
98+
#include "miscadmin.h"
9899
#include "utils/lsyscache.h"
99100
#include "utils/memutils.h"
100101

@@ -610,6 +611,8 @@ ExecMergeJoin(MergeJoinState *node)
610611
bool doFillOuter;
611612
bool doFillInner;
612613

614+
CHECK_FOR_INTERRUPTS();
615+
613616
/*
614617
* get information from node
615618
*/

src/backend/executor/nodeModifyTable.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,6 +1551,8 @@ ExecModifyTable(ModifyTableState *node)
15511551
HeapTupleData oldtupdata;
15521552
HeapTuple oldtuple;
15531553

1554+
CHECK_FOR_INTERRUPTS();
1555+
15541556
/*
15551557
* This should NOT get called during EvalPlanQual; we should have passed a
15561558
* subplan tree to EvalPlanQual, instead. Use a runtime test not just

src/backend/executor/nodeNestloop.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include "executor/execdebug.h"
2525
#include "executor/nodeNestloop.h"
26+
#include "miscadmin.h"
2627
#include "utils/memutils.h"
2728

2829

@@ -69,6 +70,8 @@ ExecNestLoop(NestLoopState *node)
6970
ExprContext *econtext;
7071
ListCell *lc;
7172

73+
CHECK_FOR_INTERRUPTS();
74+
7275
/*
7376
* get information from the node
7477
*/

src/backend/executor/nodeProjectSet.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include "executor/executor.h"
2626
#include "executor/nodeProjectSet.h"
27+
#include "miscadmin.h"
2728
#include "nodes/nodeFuncs.h"
2829
#include "utils/memutils.h"
2930

@@ -46,6 +47,8 @@ ExecProjectSet(ProjectSetState *node)
4647
PlanState *outerPlan;
4748
ExprContext *econtext;
4849

50+
CHECK_FOR_INTERRUPTS();
51+
4952
econtext = node->ps.ps_ExprContext;
5053

5154
/*

src/backend/executor/nodeRecursiveunion.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ ExecRecursiveUnion(RecursiveUnionState *node)
7575
TupleTableSlot *slot;
7676
bool isnew;
7777

78+
CHECK_FOR_INTERRUPTS();
79+
7880
/* 1. Evaluate non-recursive term */
7981
if (!node->recursing)
8082
{

src/backend/executor/nodeResult.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747

4848
#include "executor/executor.h"
4949
#include "executor/nodeResult.h"
50+
#include "miscadmin.h"
5051
#include "utils/memutils.h"
5152

5253

@@ -70,6 +71,8 @@ ExecResult(ResultState *node)
7071
PlanState *outerPlan;
7172
ExprContext *econtext;
7273

74+
CHECK_FOR_INTERRUPTS();
75+
7376
econtext = node->ps.ps_ExprContext;
7477

7578
/*

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