diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index 554244ff71f..008b2e592ff 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -801,6 +801,19 @@ ExecShutdownNode(PlanState *node) if (node == NULL) return false; + /* + * Treat the node as running while we shut it down, but only if it's run + * at least once already. We don't expect much CPU consumption during + * node shutdown, but in the case of Gather or Gather Merge, we may shut + * down workers at this stage. If so, their buffer usage will get + * propagated into pgBufferUsage at this point, and we want to make sure + * that it gets associated with the Gather node. We skip this if the node + * has never been executed, so as to avoid incorrectly making it appear + * that it has. + */ + if (node->instrument && node->instrument->running) + InstrStartNode(node->instrument); + switch (nodeTag(node)) { case T_GatherState: @@ -810,5 +823,9 @@ ExecShutdownNode(PlanState *node) break; } + /* Stop the node if we started it above, reporting 0 tuples. */ + if (node->instrument && node->instrument->running) + InstrStopNode(node->instrument, 0); + return planstate_tree_walker(node, ExecShutdownNode, NULL); } diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c index faf32e1aeed..4ff8982cd5b 100644 --- a/src/backend/executor/nodeLimit.c +++ b/src/backend/executor/nodeLimit.c @@ -130,6 +130,8 @@ ExecLimit(LimitState *node) node->position - node->offset >= node->count) { node->lstate = LIMIT_WINDOWEND; + /* Allow nodes to release or shut down resources. */ + (void) ExecShutdownNode(outerPlan); return NULL; }