mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Fix WaitEventSet resource leak in WaitLatchOrSocket().
This function would have the same issue we solved in commit501cfd07d: If an error is thrown after calling CreateWaitEventSet(), the file descriptor (on epoll- or kqueue-based systems) or handles (on Windows) that the WaitEventSet contains are leaked. Like that commit, use PG_TRY-PG_FINALLY (PG_TRY-PG_CATCH in v12) to make sure the WaitEventSet is freed properly. Back-patch to all supported versions, but as we do not have this issue in HEAD (cf. commit50c67c201), no need to apply this patch to it. Discussion: https://postgr.es/m/CAPmGK16MqdDoD8oatp8SQWaEa4vS3nfQqDN_Sj9YRuu5J3Lj9g%40mail.gmail.com
This commit is contained in:
		@@ -545,48 +545,54 @@ WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock,
 | 
			
		||||
	WaitEvent	event;
 | 
			
		||||
	WaitEventSet *set = CreateWaitEventSet(CurrentMemoryContext, 3);
 | 
			
		||||
 | 
			
		||||
	if (wakeEvents & WL_TIMEOUT)
 | 
			
		||||
		Assert(timeout >= 0);
 | 
			
		||||
	else
 | 
			
		||||
		timeout = -1;
 | 
			
		||||
 | 
			
		||||
	if (wakeEvents & WL_LATCH_SET)
 | 
			
		||||
		AddWaitEventToSet(set, WL_LATCH_SET, PGINVALID_SOCKET,
 | 
			
		||||
						  latch, NULL);
 | 
			
		||||
 | 
			
		||||
	/* Postmaster-managed callers must handle postmaster death somehow. */
 | 
			
		||||
	Assert(!IsUnderPostmaster ||
 | 
			
		||||
		   (wakeEvents & WL_EXIT_ON_PM_DEATH) ||
 | 
			
		||||
		   (wakeEvents & WL_POSTMASTER_DEATH));
 | 
			
		||||
 | 
			
		||||
	if ((wakeEvents & WL_POSTMASTER_DEATH) && IsUnderPostmaster)
 | 
			
		||||
		AddWaitEventToSet(set, WL_POSTMASTER_DEATH, PGINVALID_SOCKET,
 | 
			
		||||
						  NULL, NULL);
 | 
			
		||||
 | 
			
		||||
	if ((wakeEvents & WL_EXIT_ON_PM_DEATH) && IsUnderPostmaster)
 | 
			
		||||
		AddWaitEventToSet(set, WL_EXIT_ON_PM_DEATH, PGINVALID_SOCKET,
 | 
			
		||||
						  NULL, NULL);
 | 
			
		||||
 | 
			
		||||
	if (wakeEvents & WL_SOCKET_MASK)
 | 
			
		||||
	PG_TRY();
 | 
			
		||||
	{
 | 
			
		||||
		int			ev;
 | 
			
		||||
		if (wakeEvents & WL_TIMEOUT)
 | 
			
		||||
			Assert(timeout >= 0);
 | 
			
		||||
		else
 | 
			
		||||
			timeout = -1;
 | 
			
		||||
 | 
			
		||||
		ev = wakeEvents & WL_SOCKET_MASK;
 | 
			
		||||
		AddWaitEventToSet(set, ev, sock, NULL, NULL);
 | 
			
		||||
		if (wakeEvents & WL_LATCH_SET)
 | 
			
		||||
			AddWaitEventToSet(set, WL_LATCH_SET, PGINVALID_SOCKET,
 | 
			
		||||
							  latch, NULL);
 | 
			
		||||
 | 
			
		||||
		/* Postmaster-managed callers must handle postmaster death somehow. */
 | 
			
		||||
		Assert(!IsUnderPostmaster ||
 | 
			
		||||
			   (wakeEvents & WL_EXIT_ON_PM_DEATH) ||
 | 
			
		||||
			   (wakeEvents & WL_POSTMASTER_DEATH));
 | 
			
		||||
 | 
			
		||||
		if ((wakeEvents & WL_POSTMASTER_DEATH) && IsUnderPostmaster)
 | 
			
		||||
			AddWaitEventToSet(set, WL_POSTMASTER_DEATH, PGINVALID_SOCKET,
 | 
			
		||||
							  NULL, NULL);
 | 
			
		||||
 | 
			
		||||
		if ((wakeEvents & WL_EXIT_ON_PM_DEATH) && IsUnderPostmaster)
 | 
			
		||||
			AddWaitEventToSet(set, WL_EXIT_ON_PM_DEATH, PGINVALID_SOCKET,
 | 
			
		||||
							  NULL, NULL);
 | 
			
		||||
 | 
			
		||||
		if (wakeEvents & WL_SOCKET_MASK)
 | 
			
		||||
		{
 | 
			
		||||
			int			ev;
 | 
			
		||||
 | 
			
		||||
			ev = wakeEvents & WL_SOCKET_MASK;
 | 
			
		||||
			AddWaitEventToSet(set, ev, sock, NULL, NULL);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		rc = WaitEventSetWait(set, timeout, &event, 1, wait_event_info);
 | 
			
		||||
 | 
			
		||||
		if (rc == 0)
 | 
			
		||||
			ret |= WL_TIMEOUT;
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			ret |= event.events & (WL_LATCH_SET |
 | 
			
		||||
								   WL_POSTMASTER_DEATH |
 | 
			
		||||
								   WL_SOCKET_MASK);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rc = WaitEventSetWait(set, timeout, &event, 1, wait_event_info);
 | 
			
		||||
 | 
			
		||||
	if (rc == 0)
 | 
			
		||||
		ret |= WL_TIMEOUT;
 | 
			
		||||
	else
 | 
			
		||||
	PG_FINALLY();
 | 
			
		||||
	{
 | 
			
		||||
		ret |= event.events & (WL_LATCH_SET |
 | 
			
		||||
							   WL_POSTMASTER_DEATH |
 | 
			
		||||
							   WL_SOCKET_MASK);
 | 
			
		||||
		FreeWaitEventSet(set);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	FreeWaitEventSet(set);
 | 
			
		||||
	PG_END_TRY();
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user