Allow WaitLatch() to be used without a latch.
Due to flaws in commit 3347c982ba
, 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
This commit is contained in:
parent
2e3c19462d
commit
733fa9aa51
|
@ -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,
|
||||||
/* 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,
|
||||||
/* 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,
|
||||||
/* 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,
|
||||||
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;
|
||||||
|
|
Loading…
Reference in New Issue