Commit 733fa9aa authored by Thomas Munro's avatar Thomas Munro

Allow WaitLatch() to be used without a latch.

Due to flaws in commit 3347c982, 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
parent 2e3c1946
...@@ -924,7 +924,22 @@ ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch) ...@@ -924,7 +924,22 @@ ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch)
if (events == WL_LATCH_SET) if (events == WL_LATCH_SET)
{ {
if (latch && latch->owner_pid != MyProcPid)
elog(ERROR, "cannot wait on a latch owned by another process");
set->latch = latch; set->latch = latch;
/*
* On Unix, we don't need to modify the kernel object because the
* underlying pipe is the same for all latches so we can return
* immediately. On Windows, we need to update our array of handles,
* but we leave the old one in place and tolerate spurious wakeups if
* the latch is disabled.
*/
#if defined(WAIT_USE_WIN32)
if (!latch)
return;
#else
return;
#endif
} }
#if defined(WAIT_USE_EPOLL) #if defined(WAIT_USE_EPOLL)
...@@ -1386,7 +1401,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, ...@@ -1386,7 +1401,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
/* There's data in the self-pipe, clear it. */ /* There's data in the self-pipe, clear it. */
drainSelfPipe(); drainSelfPipe();
if (set->latch->is_set) if (set->latch && set->latch->is_set)
{ {
occurred_events->fd = PGINVALID_SOCKET; occurred_events->fd = PGINVALID_SOCKET;
occurred_events->events = WL_LATCH_SET; occurred_events->events = WL_LATCH_SET;
...@@ -1536,7 +1551,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, ...@@ -1536,7 +1551,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
/* There's data in the self-pipe, clear it. */ /* There's data in the self-pipe, clear it. */
drainSelfPipe(); drainSelfPipe();
if (set->latch->is_set) if (set->latch && set->latch->is_set)
{ {
occurred_events->fd = PGINVALID_SOCKET; occurred_events->fd = PGINVALID_SOCKET;
occurred_events->events = WL_LATCH_SET; occurred_events->events = WL_LATCH_SET;
...@@ -1645,7 +1660,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, ...@@ -1645,7 +1660,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
/* There's data in the self-pipe, clear it. */ /* There's data in the self-pipe, clear it. */
drainSelfPipe(); drainSelfPipe();
if (set->latch->is_set) if (set->latch && set->latch->is_set)
{ {
occurred_events->fd = PGINVALID_SOCKET; occurred_events->fd = PGINVALID_SOCKET;
occurred_events->events = WL_LATCH_SET; occurred_events->events = WL_LATCH_SET;
...@@ -1812,7 +1827,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, ...@@ -1812,7 +1827,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
if (!ResetEvent(set->latch->event)) if (!ResetEvent(set->latch->event))
elog(ERROR, "ResetEvent failed: error code %lu", GetLastError()); elog(ERROR, "ResetEvent failed: error code %lu", GetLastError());
if (set->latch->is_set) if (set->latch && set->latch->is_set)
{ {
occurred_events->fd = PGINVALID_SOCKET; occurred_events->fd = PGINVALID_SOCKET;
occurred_events->events = WL_LATCH_SET; occurred_events->events = WL_LATCH_SET;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment