From 89b183622d4efbacce8027e8dd29336a7d3182b1 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Mon, 3 Mar 2025 17:11:06 +0200 Subject: [PATCH 1/1] 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. --- src/backend/executor/nodeAppend.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index ca0f54d676f..a03a23c18e4 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -326,6 +326,8 @@ ExecAppend(PlanState *pstate) { PlanState *subnode; + ResetLatch(MyLatch); + CHECK_FOR_INTERRUPTS(); /* @@ -1016,7 +1018,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; @@ -1041,8 +1043,7 @@ ExecAppendAsyncEventWait(AppendState *node) } /* - * No need for further processing if there are no configured events other - * than the postmaster death event. + * No need for further processing if none of the subplans configured any events. */ if (GetNumRegisteredWaitEvents(node->as_eventset) == 1) { @@ -1051,6 +1052,21 @@ ExecAppendAsyncEventWait(AppendState *node) return; } + /* + * Add the 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 bad 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; -- 2.39.5