From 0341d4b10e786dcbc4c63da9d21af842ab31e118 Mon Sep 17 00:00:00 2001 From: Etsuro Fujita Date: Thu, 11 Apr 2024 19:05:07 +0900 Subject: [PATCH] Fix WaitEventSet resource leak in WaitLatchOrSocket(). This function would have the same issue we solved in commit 501cfd07d: 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. commit 50c67c201), no need to apply this patch to it. Discussion: https://postgr.es/m/CAPmGK16MqdDoD8oatp8SQWaEa4vS3nfQqDN_Sj9YRuu5J3Lj9g%40mail.gmail.com --- src/backend/storage/ipc/latch.c | 79 ++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c index d35b7ee7d1..d5f7f8d636 100644 --- a/src/backend/storage/ipc/latch.c +++ b/src/backend/storage/ipc/latch.c @@ -374,46 +374,55 @@ 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_CATCH(); { - ret |= event.events & (WL_LATCH_SET | - WL_POSTMASTER_DEATH | - WL_SOCKET_MASK); + FreeWaitEventSet(set); + PG_RE_THROW(); } + PG_END_TRY(); FreeWaitEventSet(set);