diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2025-03-12 20:53:09 +0200 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2025-03-12 20:53:09 +0200 |
commit | af717317a04f5217728ce296edf4a581eb7e6ea0 (patch) | |
tree | 0163953a45bfef62e143f5277b5a5bdaa68813c5 /src/backend/executor/nodeAppend.c | |
parent | f4e7756ef9a437f30a4dc5ded41b8824a9d291b9 (diff) | |
download | postgresql-af717317a04f5217728ce296edf4a581eb7e6ea0.tar.gz postgresql-af717317a04f5217728ce296edf4a581eb7e6ea0.zip |
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
Diffstat (limited to 'src/backend/executor/nodeAppend.c')
-rw-r--r-- | src/backend/executor/nodeAppend.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index 15c4227cc62..a11b36c7176 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -1031,7 +1031,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; @@ -1056,8 +1056,8 @@ 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) { @@ -1066,6 +1066,21 @@ ExecAppendAsyncEventWait(AppendState *node) return; } + /* + * 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; @@ -1107,6 +1122,13 @@ ExecAppendAsyncEventWait(AppendState *node) ExecAsyncNotify(areq); } } + + /* Handle standard interrupts */ + if ((w->events & WL_LATCH_SET) != 0) + { + ResetLatch(MyLatch); + CHECK_FOR_INTERRUPTS(); + } } } |