From e79ceafe93a85820188e835adb392d38331ceed2 Mon Sep 17 00:00:00 2001 From: Etsuro Fujita Date: Thu, 11 Apr 2024 19:05:00 +0900 Subject: 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 | 70 ++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c index cdb95c1931a..767328039e3 100644 --- a/src/backend/storage/ipc/latch.c +++ b/src/backend/storage/ipc/latch.c @@ -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; + PG_TRY(); + { + if (wakeEvents & WL_TIMEOUT) + Assert(timeout >= 0); + else + timeout = -1; - if (wakeEvents & WL_LATCH_SET) - AddWaitEventToSet(set, WL_LATCH_SET, PGINVALID_SOCKET, - latch, 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)); + /* 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_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_EXIT_ON_PM_DEATH) && IsUnderPostmaster) + AddWaitEventToSet(set, WL_EXIT_ON_PM_DEATH, PGINVALID_SOCKET, + NULL, NULL); - if (wakeEvents & WL_SOCKET_MASK) - { - int ev; + if (wakeEvents & WL_SOCKET_MASK) + { + int ev; - ev = wakeEvents & WL_SOCKET_MASK; - AddWaitEventToSet(set, ev, sock, NULL, NULL); - } + ev = wakeEvents & WL_SOCKET_MASK; + AddWaitEventToSet(set, ev, sock, NULL, NULL); + } - rc = WaitEventSetWait(set, timeout, &event, 1, wait_event_info); + rc = WaitEventSetWait(set, timeout, &event, 1, wait_event_info); - if (rc == 0) - ret |= WL_TIMEOUT; - else + if (rc == 0) + ret |= WL_TIMEOUT; + else + { + ret |= event.events & (WL_LATCH_SET | + WL_POSTMASTER_DEATH | + WL_SOCKET_MASK); + } + } + PG_FINALLY(); { - ret |= event.events & (WL_LATCH_SET | - WL_POSTMASTER_DEATH | - WL_SOCKET_MASK); + FreeWaitEventSet(set); } - - FreeWaitEventSet(set); + PG_END_TRY(); return ret; } -- cgit v1.2.3