aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEtsuro Fujita <efujita@postgresql.org>2024-04-11 19:05:00 +0900
committerEtsuro Fujita <efujita@postgresql.org>2024-04-11 19:05:00 +0900
commite79ceafe93a85820188e835adb392d38331ceed2 (patch)
tree442dfbc852bddcd95903b92985784298fe0be596
parent574c7c754666a2b5634efd700d3602629d261362 (diff)
downloadpostgresql-e79ceafe93a85820188e835adb392d38331ceed2.tar.gz
postgresql-e79ceafe93a85820188e835adb392d38331ceed2.zip
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
-rw-r--r--src/backend/storage/ipc/latch.c70
1 files 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;
}