1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-19 15:49:24 +03:00

Attempt to fix some issues in our Windows socket code.

Make sure WaitLatchOrSocket regards FD_CLOSE as a read-ready condition.
We might want to tweak this further, but it was surely wrong as-is.

Make pgwin32_waitforsinglesocket detach its private event object from the
passed socket before returning.  I suspect that failure to do so leads
to race conditions when other code (such as WaitLatchOrSocket) attaches
a different event object to the same socket.  Moreover, the existing
coding meant that repeated calls to pgwin32_waitforsinglesocket would
perform ResetEvent on an event actively connected to a socket, which
is rumored to be an unsafe practice; the WSAEventSelect documentation
appears to recommend against this, though it does not say not to do it
in so many words.

Also, uniformly use the coding pattern "WSAEventSelect(s, NULL, 0)" to
detach events from sockets, rather than passing the event in the second
parameter.  The WSAEventSelect documentation says that the second parameter
is ignored if the third is 0, so theoretically this should make no
difference.  However, elsewhere on the same reference page the use of NULL
in this context is recommended, and I have found suggestions on the net
that some versions of Windows have bugs with a non-NULL second parameter
in this usage.

Some other mostly-cosmetic cleanup, such as using the right one of
WSAGetLastError and GetLastError for reporting errors from these functions.
This commit is contained in:
Tom Lane
2012-05-13 14:35:40 -04:00
parent fd350ef395
commit b85427f227
2 changed files with 36 additions and 23 deletions

View File

@@ -130,10 +130,11 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
numevents = 2;
if (wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE))
{
/* Need an event object to represent events on the socket */
int flags = 0;
if (wakeEvents & WL_SOCKET_READABLE)
flags |= FD_READ;
flags |= (FD_READ | FD_CLOSE);
if (wakeEvents & WL_SOCKET_WRITEABLE)
flags |= FD_WRITE;
@@ -201,11 +202,11 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
WSANETWORKEVENTS resEvents;
ZeroMemory(&resEvents, sizeof(resEvents));
if (WSAEnumNetworkEvents(sock, sockevent, &resEvents) == SOCKET_ERROR)
elog(ERROR, "failed to enumerate network events: error code %lu",
GetLastError());
if (WSAEnumNetworkEvents(sock, sockevent, &resEvents) != 0)
elog(ERROR, "failed to enumerate network events: error code %u",
WSAGetLastError());
if ((wakeEvents & WL_SOCKET_READABLE) &&
(resEvents.lNetworkEvents & FD_READ))
(resEvents.lNetworkEvents & (FD_READ | FD_CLOSE)))
{
result |= WL_SOCKET_READABLE;
}
@@ -233,10 +234,10 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
}
while (result == 0);
/* Clean up the handle we created for the socket */
/* Clean up the event object we created for the socket */
if (sockevent != WSA_INVALID_EVENT)
{
WSAEventSelect(sock, sockevent, 0);
WSAEventSelect(sock, NULL, 0);
WSACloseEvent(sockevent);
}