Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit de35a97

Browse files
committed
Handle WAIT_IO_COMPLETION return from WaitForMultipleObjectsEx().
This return code is possible wherever we pass bAlertable = TRUE; it arises when Windows caused the current thread to run an "I/O completion routine" or an "asynchronous procedure call". PostgreSQL does not provoke either of those Windows facilities, hence this bug remaining largely unnoticed, but other local code might do so. Due to a shortage of complaints, no back-patch for now. Per report from Shiv Shivaraju Gowda, this bug can cause PGSemaphoreLock() to PANIC. The bug can also cause select() to report timeout expiration too early, which might confuse pgstat_init() and CheckRADIUSAuth().
1 parent e565ff7 commit de35a97

File tree

2 files changed

+37
-24
lines changed

2 files changed

+37
-24
lines changed

src/backend/port/win32/socket.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,8 @@ pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, c
623623
return 0;
624624
}
625625

626-
if (r == WAIT_OBJECT_0 + numevents)
626+
/* Signal-like events. */
627+
if (r == WAIT_OBJECT_0 + numevents || r == WAIT_IO_COMPLETION)
627628
{
628629
pgwin32_dispatch_queued_signals();
629630
errno = EINTR;

src/backend/port/win32_sema.c

+35-23
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,10 @@ PGSemaphoreReset(PGSemaphore sema)
118118
void
119119
PGSemaphoreLock(PGSemaphore sema, bool interruptOK)
120120
{
121-
DWORD ret;
122121
HANDLE wh[2];
122+
bool done = false;
123+
124+
ImmediateInterruptOK = interruptOK;
123125

124126
/*
125127
* Note: pgwin32_signal_event should be first to ensure that it will be
@@ -135,34 +137,44 @@ PGSemaphoreLock(PGSemaphore sema, bool interruptOK)
135137
* no hidden magic about whether the syscall will internally service a
136138
* signal --- we do that ourselves.
137139
*/
138-
do
140+
while (!done)
139141
{
140-
ImmediateInterruptOK = interruptOK;
141-
CHECK_FOR_INTERRUPTS();
142+
DWORD rc;
142143

143-
ret = WaitForMultipleObjectsEx(2, wh, FALSE, INFINITE, TRUE);
144+
CHECK_FOR_INTERRUPTS();
144145

145-
if (ret == WAIT_OBJECT_0)
146+
rc = WaitForMultipleObjectsEx(2, wh, FALSE, INFINITE, TRUE);
147+
switch (rc)
146148
{
147-
/* Signal event is set - we have a signal to deliver */
148-
pgwin32_dispatch_queued_signals();
149-
errno = EINTR;
149+
case WAIT_OBJECT_0:
150+
/* Signal event is set - we have a signal to deliver */
151+
pgwin32_dispatch_queued_signals();
152+
break;
153+
case WAIT_OBJECT_0 + 1:
154+
/* We got it! */
155+
done = true;
156+
break;
157+
case WAIT_IO_COMPLETION:
158+
/*
159+
* The system interrupted the wait to execute an I/O
160+
* completion routine or asynchronous procedure call in this
161+
* thread. PostgreSQL does not provoke either of these, but
162+
* atypical loaded DLLs or even other processes might do so.
163+
* Now, resume waiting.
164+
*/
165+
break;
166+
case WAIT_FAILED:
167+
ereport(FATAL,
168+
(errmsg("could not lock semaphore: error code %lu",
169+
GetLastError())));
170+
break;
171+
default:
172+
elog(FATAL, "unexpected return code from WaitForMultipleObjectsEx(): %lu", rc);
173+
break;
150174
}
151-
else if (ret == WAIT_OBJECT_0 + 1)
152-
{
153-
/* We got it! */
154-
errno = 0;
155-
}
156-
else
157-
/* Otherwise we are in trouble */
158-
errno = EIDRM;
159-
160-
ImmediateInterruptOK = false;
161-
} while (errno == EINTR);
175+
}
162176

163-
if (errno != 0)
164-
ereport(FATAL,
165-
(errmsg("could not lock semaphore: error code %lu", GetLastError())));
177+
ImmediateInterruptOK = false;
166178
}
167179

168180
/*

0 commit comments

Comments
 (0)