summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2025-03-12 20:53:09 +0200
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2025-03-12 20:53:23 +0200
commitd4d34c08c75741dc2dd667fda0946ee1f6eb1544 (patch)
treeab3bf499eeeac4612c95c32fd2369a88e2ad806f
parentae0be2f0bd726fd0f094279ab044b25e185b2ed2 (diff)
Handle interrupts while waiting on Append's async subplans
We did not wake up on interrupts while waiting on async events on an async-capable append node. For example, if you tried to cancel the query, nothing would happen until one of the async subplans becomes readable. To fix, add WL_LATCH_SET to the WaitEventSet. Backpatch down to v14 where async Append execution was introduced. Discussion: https://www.postgresql.org/message-id/37a40570-f558-40d3-b5ea-5c2079b3b30b@iki.fi
-rw-r--r--src/backend/executor/nodeAppend.c28
1 files changed, 25 insertions, 3 deletions
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c
index 0509ee22fc4..dcc97ffef23 100644
--- a/src/backend/executor/nodeAppend.c
+++ b/src/backend/executor/nodeAppend.c
@@ -1007,7 +1007,7 @@ ExecAppendAsyncRequest(AppendState *node, TupleTableSlot **result)
static void
ExecAppendAsyncEventWait(AppendState *node)
{
- int nevents = node->as_nasyncplans + 1;
+ int nevents = node->as_nasyncplans + 2;
long timeout = node->as_syncdone ? -1 : 0;
WaitEvent occurred_event[EVENT_BUFFER_SIZE];
int noccurred;
@@ -1034,13 +1034,28 @@ ExecAppendAsyncEventWait(AppendState *node)
}
/*
- * If there are no configured events other than the postmaster death
- * event, we don't need to wait or poll.
+ * No need for further processing if none of the subplans configured
+ * any events.
*/
if (GetNumRegisteredWaitEvents(node->as_eventset) == 1)
noccurred = 0;
else
{
+ /*
+ * Add the process latch to the set, so that we wake up to process
+ * the standard interrupts with CHECK_FOR_INTERRUPTS().
+ *
+ * NOTE: For historical reasons, it's important that this is added
+ * to the WaitEventSet after the ExecAsyncConfigureWait() calls.
+ * Namely, postgres_fdw calls "GetNumRegisteredWaitEvents(set) ==
+ * 1" to check if any other events are in the set. That's a poor
+ * design, it's questionable for postgres_fdw to be doing that in
+ * the first place, but we cannot change it now. The pattern has
+ * possibly been copied to other extensions too.
+ */
+ AddWaitEventToSet(node->as_eventset, WL_LATCH_SET, PGINVALID_SOCKET,
+ MyLatch, NULL);
+
/* Return at most EVENT_BUFFER_SIZE events in one call. */
if (nevents > EVENT_BUFFER_SIZE)
nevents = EVENT_BUFFER_SIZE;
@@ -1089,6 +1104,13 @@ ExecAppendAsyncEventWait(AppendState *node)
ExecAsyncNotify(areq);
}
}
+
+ /* Handle standard interrupts */
+ if ((w->events & WL_LATCH_SET) != 0)
+ {
+ ResetLatch(MyLatch);
+ CHECK_FOR_INTERRUPTS();
+ }
}
}