Commit 8ebc908c authored by Tom Lane's avatar Tom Lane

Improve Windows implementation of WaitLatch/WaitLatchOrSocket.

Ensure that signal handlers are serviced before this function returns.
This should make the behavior more like Unix.  Also, add some more
error checking, and make some other cosmetic improvements.

No back-patch since it's not clear whether this is fixing any live bug
that would affect 9.1.  I'm more concerned about 9.2 anyway given our
considerable recent expansions in the usage of WaitLatch.
parent 53216e39
...@@ -115,14 +115,19 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock, ...@@ -115,14 +115,19 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
else else
timeout = INFINITE; timeout = INFINITE;
/* Construct an array of event handles for WaitforMultipleObjects() */ /*
* Construct an array of event handles for WaitforMultipleObjects().
*
* Note: pgwin32_signal_event should be first to ensure that it will be
* reported when multiple events are set. We want to guarantee that
* pending signals are serviced.
*/
latchevent = latch->event; latchevent = latch->event;
events[0] = latchevent; events[0] = pgwin32_signal_event;
events[1] = pgwin32_signal_event; events[1] = latchevent;
numevents = 2; numevents = 2;
if ((wakeEvents & WL_SOCKET_READABLE) || if (wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE))
(wakeEvents & WL_SOCKET_WRITEABLE))
{ {
int flags = 0; int flags = 0;
...@@ -132,7 +137,13 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock, ...@@ -132,7 +137,13 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
flags |= FD_WRITE; flags |= FD_WRITE;
sockevent = WSACreateEvent(); sockevent = WSACreateEvent();
WSAEventSelect(sock, sockevent, flags); if (sockevent == WSA_INVALID_EVENT)
elog(ERROR, "failed to create event for socket: error code %u",
WSAGetLastError());
if (WSAEventSelect(sock, sockevent, flags) != 0)
elog(ERROR, "failed to set up event for socket: error code %u",
WSAGetLastError());
events[numevents++] = sockevent; events[numevents++] = sockevent;
} }
if (wakeEvents & WL_POSTMASTER_DEATH) if (wakeEvents & WL_POSTMASTER_DEATH)
...@@ -141,6 +152,9 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock, ...@@ -141,6 +152,9 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
events[numevents++] = PostmasterHandle; events[numevents++] = PostmasterHandle;
} }
/* Ensure that signals are serviced even if latch is already set */
pgwin32_dispatch_queued_signals();
do do
{ {
/* /*
...@@ -151,6 +165,7 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock, ...@@ -151,6 +165,7 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
*/ */
if (!ResetEvent(latchevent)) if (!ResetEvent(latchevent))
elog(ERROR, "ResetEvent failed: error code %lu", GetLastError()); elog(ERROR, "ResetEvent failed: error code %lu", GetLastError());
if ((wakeEvents & WL_LATCH_SET) && latch->is_set) if ((wakeEvents & WL_LATCH_SET) && latch->is_set)
{ {
result |= WL_LATCH_SET; result |= WL_LATCH_SET;
...@@ -164,21 +179,20 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock, ...@@ -164,21 +179,20 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
rc = WaitForMultipleObjects(numevents, events, FALSE, timeout); rc = WaitForMultipleObjects(numevents, events, FALSE, timeout);
if (rc == WAIT_FAILED) if (rc == WAIT_FAILED)
elog(ERROR, "WaitForMultipleObjects() failed: error code %lu", GetLastError()); elog(ERROR, "WaitForMultipleObjects() failed: error code %lu",
GetLastError());
/* Participate in Windows signal emulation */
else if (rc == WAIT_OBJECT_0 + 1)
pgwin32_dispatch_queued_signals();
else if (rc == WAIT_TIMEOUT) else if (rc == WAIT_TIMEOUT)
{ {
result |= WL_TIMEOUT; result |= WL_TIMEOUT;
} }
else if ((wakeEvents & WL_POSTMASTER_DEATH) && else if (rc == WAIT_OBJECT_0)
rc == WAIT_OBJECT_0 + pmdeath_eventno)
{ {
/* Postmaster died */ /* Service newly-arrived signals */
result |= WL_POSTMASTER_DEATH; pgwin32_dispatch_queued_signals();
}
else if (rc == WAIT_OBJECT_0 + 1)
{
/* Latch is set, we'll handle that on next iteration of loop */
} }
else if ((wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) && else if ((wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) &&
rc == WAIT_OBJECT_0 + 2) /* socket is at event slot 2 */ rc == WAIT_OBJECT_0 + 2) /* socket is at event slot 2 */
...@@ -187,9 +201,8 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock, ...@@ -187,9 +201,8 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
ZeroMemory(&resEvents, sizeof(resEvents)); ZeroMemory(&resEvents, sizeof(resEvents));
if (WSAEnumNetworkEvents(sock, sockevent, &resEvents) == SOCKET_ERROR) if (WSAEnumNetworkEvents(sock, sockevent, &resEvents) == SOCKET_ERROR)
ereport(FATAL, elog(ERROR, "failed to enumerate network events: error code %lu",
(errmsg_internal("failed to enumerate network events: error code %lu", GetLastError()))); GetLastError());
if ((wakeEvents & WL_SOCKET_READABLE) && if ((wakeEvents & WL_SOCKET_READABLE) &&
(resEvents.lNetworkEvents & FD_READ)) (resEvents.lNetworkEvents & FD_READ))
{ {
...@@ -201,8 +214,13 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock, ...@@ -201,8 +214,13 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
result |= WL_SOCKET_WRITEABLE; result |= WL_SOCKET_WRITEABLE;
} }
} }
/* Otherwise it must be the latch event */ else if ((wakeEvents & WL_POSTMASTER_DEATH) &&
else if (rc != WAIT_OBJECT_0) rc == WAIT_OBJECT_0 + pmdeath_eventno)
{
/* Postmaster died */
result |= WL_POSTMASTER_DEATH;
}
else
elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %lu", rc); elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %lu", rc);
} }
while (result == 0); while (result == 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment