diff options
author | Thomas Munro <tmunro@postgresql.org> | 2020-09-23 15:17:30 +1200 |
---|---|---|
committer | Thomas Munro <tmunro@postgresql.org> | 2020-09-23 15:17:30 +1200 |
commit | 733fa9aa51c526582f100aa0d375e0eb9a6bce8b (patch) | |
tree | 8334a2108975ccb7cc4336fd76bccae9a2453a9a /src | |
parent | 2e3c19462da930d1d018caa3daabca00159b4b18 (diff) | |
download | postgresql-733fa9aa51c526582f100aa0d375e0eb9a6bce8b.tar.gz postgresql-733fa9aa51c526582f100aa0d375e0eb9a6bce8b.zip |
Allow WaitLatch() to be used without a latch.
Due to flaws in commit 3347c982bab, 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
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/storage/ipc/latch.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c index 4153cc85579..63c6c975360 100644 --- a/src/backend/storage/ipc/latch.c +++ b/src/backend/storage/ipc/latch.c @@ -924,7 +924,22 @@ ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch) 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; + /* + * 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) @@ -1386,7 +1401,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, /* There's data in the self-pipe, clear it. */ drainSelfPipe(); - if (set->latch->is_set) + if (set->latch && set->latch->is_set) { occurred_events->fd = PGINVALID_SOCKET; 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. */ drainSelfPipe(); - if (set->latch->is_set) + if (set->latch && set->latch->is_set) { occurred_events->fd = PGINVALID_SOCKET; 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. */ drainSelfPipe(); - if (set->latch->is_set) + if (set->latch && set->latch->is_set) { occurred_events->fd = PGINVALID_SOCKET; occurred_events->events = WL_LATCH_SET; @@ -1812,7 +1827,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, if (!ResetEvent(set->latch->event)) 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->events = WL_LATCH_SET; |