mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-29 22:49:41 +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:
		| @@ -1020,7 +1020,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; | ||||||
| @@ -1047,13 +1047,28 @@ ExecAppendAsyncEventWait(AppendState *node) | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		/* | 		/* | ||||||
| 		 * If there are no configured events other than the postmaster death | 		 * No need for further processing if none of the subplans configured | ||||||
| 		 * event, we don't need to wait or poll. | 		 * any events. | ||||||
| 		 */ | 		 */ | ||||||
| 		if (GetNumRegisteredWaitEvents(node->as_eventset) == 1) | 		if (GetNumRegisteredWaitEvents(node->as_eventset) == 1) | ||||||
| 			noccurred = 0; | 			noccurred = 0; | ||||||
| 		else | 		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. */ | 			/* 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; | ||||||
| @@ -1102,6 +1117,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