Skip to content

Commit 733fa9a

Browse files
committed
Allow WaitLatch() to be used without a latch.
Due to flaws in commit 3347c98, using WaitLatch() without WL_LATCH_SET could cause an assertion failure or crash. Repair. While here, also add a check that the latch we're switching to belongs to this backend, when changing from one latch to another. Discussion: https://postgr.es/m/CA%2BhUKGK1607VmtrDUHQXrsooU%3Dap4g4R2yaoByWOOA3m8xevUQ%40mail.gmail.com
1 parent 2e3c194 commit 733fa9a

File tree

1 file changed

+19
-4
lines changed

1 file changed

+19
-4
lines changed

src/backend/storage/ipc/latch.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -924,7 +924,22 @@ ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch)
924924

925925
if (events == WL_LATCH_SET)
926926
{
927+
if (latch && latch->owner_pid != MyProcPid)
928+
elog(ERROR, "cannot wait on a latch owned by another process");
927929
set->latch = latch;
930+
/*
931+
* On Unix, we don't need to modify the kernel object because the
932+
* underlying pipe is the same for all latches so we can return
933+
* immediately. On Windows, we need to update our array of handles,
934+
* but we leave the old one in place and tolerate spurious wakeups if
935+
* the latch is disabled.
936+
*/
937+
#if defined(WAIT_USE_WIN32)
938+
if (!latch)
939+
return;
940+
#else
941+
return;
942+
#endif
928943
}
929944

930945
#if defined(WAIT_USE_EPOLL)
@@ -1386,7 +1401,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
13861401
/* There's data in the self-pipe, clear it. */
13871402
drainSelfPipe();
13881403

1389-
if (set->latch->is_set)
1404+
if (set->latch && set->latch->is_set)
13901405
{
13911406
occurred_events->fd = PGINVALID_SOCKET;
13921407
occurred_events->events = WL_LATCH_SET;
@@ -1536,7 +1551,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
15361551
/* There's data in the self-pipe, clear it. */
15371552
drainSelfPipe();
15381553

1539-
if (set->latch->is_set)
1554+
if (set->latch && set->latch->is_set)
15401555
{
15411556
occurred_events->fd = PGINVALID_SOCKET;
15421557
occurred_events->events = WL_LATCH_SET;
@@ -1645,7 +1660,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
16451660
/* There's data in the self-pipe, clear it. */
16461661
drainSelfPipe();
16471662

1648-
if (set->latch->is_set)
1663+
if (set->latch && set->latch->is_set)
16491664
{
16501665
occurred_events->fd = PGINVALID_SOCKET;
16511666
occurred_events->events = WL_LATCH_SET;
@@ -1812,7 +1827,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
18121827
if (!ResetEvent(set->latch->event))
18131828
elog(ERROR, "ResetEvent failed: error code %lu", GetLastError());
18141829

1815-
if (set->latch->is_set)
1830+
if (set->latch && set->latch->is_set)
18161831
{
18171832
occurred_events->fd = PGINVALID_SOCKET;
18181833
occurred_events->events = WL_LATCH_SET;

0 commit comments

Comments
 (0)