mirror of
https://github.com/postgres/postgres.git
synced 2025-05-28 00:03:23 -04:00
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().
This commit is contained in:
parent
e565ff7553
commit
de35a97710
@ -623,7 +623,8 @@ pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, c
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (r == WAIT_OBJECT_0 + numevents)
|
||||
/* Signal-like events. */
|
||||
if (r == WAIT_OBJECT_0 + numevents || r == WAIT_IO_COMPLETION)
|
||||
{
|
||||
pgwin32_dispatch_queued_signals();
|
||||
errno = EINTR;
|
||||
|
@ -118,8 +118,10 @@ PGSemaphoreReset(PGSemaphore sema)
|
||||
void
|
||||
PGSemaphoreLock(PGSemaphore sema, bool interruptOK)
|
||||
{
|
||||
DWORD ret;
|
||||
HANDLE wh[2];
|
||||
bool done = false;
|
||||
|
||||
ImmediateInterruptOK = interruptOK;
|
||||
|
||||
/*
|
||||
* Note: pgwin32_signal_event should be first to ensure that it will be
|
||||
@ -135,34 +137,44 @@ PGSemaphoreLock(PGSemaphore sema, bool interruptOK)
|
||||
* no hidden magic about whether the syscall will internally service a
|
||||
* signal --- we do that ourselves.
|
||||
*/
|
||||
do
|
||||
while (!done)
|
||||
{
|
||||
ImmediateInterruptOK = interruptOK;
|
||||
DWORD rc;
|
||||
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
|
||||
ret = WaitForMultipleObjectsEx(2, wh, FALSE, INFINITE, TRUE);
|
||||
|
||||
if (ret == WAIT_OBJECT_0)
|
||||
rc = WaitForMultipleObjectsEx(2, wh, FALSE, INFINITE, TRUE);
|
||||
switch (rc)
|
||||
{
|
||||
/* Signal event is set - we have a signal to deliver */
|
||||
pgwin32_dispatch_queued_signals();
|
||||
errno = EINTR;
|
||||
case WAIT_OBJECT_0:
|
||||
/* Signal event is set - we have a signal to deliver */
|
||||
pgwin32_dispatch_queued_signals();
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
/* We got it! */
|
||||
done = true;
|
||||
break;
|
||||
case WAIT_IO_COMPLETION:
|
||||
/*
|
||||
* The system interrupted the wait to execute an I/O
|
||||
* completion routine or asynchronous procedure call in this
|
||||
* thread. PostgreSQL does not provoke either of these, but
|
||||
* atypical loaded DLLs or even other processes might do so.
|
||||
* Now, resume waiting.
|
||||
*/
|
||||
break;
|
||||
case WAIT_FAILED:
|
||||
ereport(FATAL,
|
||||
(errmsg("could not lock semaphore: error code %lu",
|
||||
GetLastError())));
|
||||
break;
|
||||
default:
|
||||
elog(FATAL, "unexpected return code from WaitForMultipleObjectsEx(): %lu", rc);
|
||||
break;
|
||||
}
|
||||
else if (ret == WAIT_OBJECT_0 + 1)
|
||||
{
|
||||
/* We got it! */
|
||||
errno = 0;
|
||||
}
|
||||
else
|
||||
/* Otherwise we are in trouble */
|
||||
errno = EIDRM;
|
||||
}
|
||||
|
||||
ImmediateInterruptOK = false;
|
||||
} while (errno == EINTR);
|
||||
|
||||
if (errno != 0)
|
||||
ereport(FATAL,
|
||||
(errmsg("could not lock semaphore: error code %lu", GetLastError())));
|
||||
ImmediateInterruptOK = false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user