aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Munro <tmunro@postgresql.org>2020-09-23 15:17:30 +1200
committerThomas Munro <tmunro@postgresql.org>2020-09-23 15:17:30 +1200
commit733fa9aa51c526582f100aa0d375e0eb9a6bce8b (patch)
tree8334a2108975ccb7cc4336fd76bccae9a2453a9a /src
parent2e3c19462da930d1d018caa3daabca00159b4b18 (diff)
downloadpostgresql-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.c23
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;