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
*/

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