mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	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
This commit is contained in:
		@@ -1016,7 +1016,7 @@ ExecAppendAsyncRequest(AppendState *node, TupleTableSlot **result)
 | 
				
			|||||||
static void
 | 
					static void
 | 
				
			||||||
ExecAppendAsyncEventWait(AppendState *node)
 | 
					ExecAppendAsyncEventWait(AppendState *node)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int			nevents = node->as_nasyncplans + 1;
 | 
						int			nevents = node->as_nasyncplans + 2;
 | 
				
			||||||
	long		timeout = node->as_syncdone ? -1 : 0;
 | 
						long		timeout = node->as_syncdone ? -1 : 0;
 | 
				
			||||||
	WaitEvent	occurred_event[EVENT_BUFFER_SIZE];
 | 
						WaitEvent	occurred_event[EVENT_BUFFER_SIZE];
 | 
				
			||||||
	int			noccurred;
 | 
						int			noccurred;
 | 
				
			||||||
@@ -1041,8 +1041,8 @@ ExecAppendAsyncEventWait(AppendState *node)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * No need for further processing if there are no configured events other
 | 
						 * No need for further processing if none of the subplans configured any
 | 
				
			||||||
	 * than the postmaster death event.
 | 
						 * events.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (GetNumRegisteredWaitEvents(node->as_eventset) == 1)
 | 
						if (GetNumRegisteredWaitEvents(node->as_eventset) == 1)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -1051,6 +1051,21 @@ ExecAppendAsyncEventWait(AppendState *node)
 | 
				
			|||||||
		return;
 | 
							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. */
 | 
						/* Return at most EVENT_BUFFER_SIZE events in one call. */
 | 
				
			||||||
	if (nevents > EVENT_BUFFER_SIZE)
 | 
						if (nevents > EVENT_BUFFER_SIZE)
 | 
				
			||||||
		nevents = EVENT_BUFFER_SIZE;
 | 
							nevents = EVENT_BUFFER_SIZE;
 | 
				
			||||||
@@ -1092,6 +1107,13 @@ ExecAppendAsyncEventWait(AppendState *node)
 | 
				
			|||||||
				ExecAsyncNotify(areq);
 | 
									ExecAsyncNotify(areq);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Handle standard interrupts */
 | 
				
			||||||
 | 
							if ((w->events & WL_LATCH_SET) != 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ResetLatch(MyLatch);
 | 
				
			||||||
 | 
								CHECK_FOR_INTERRUPTS();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user