Back-patch fixes for some issues in our Windows socket code into 9.1.

This is a backport of commit b85427f2276d02756b558c0024949305ea65aca5.
Per discussion of bug #4958.  Some of these fixes probably need to be
back-patched further, but I'm just doing this much for now.
This commit is contained in:
Robert Haas 2012-08-27 15:00:08 -04:00
parent 180ce0af33
commit ed597d0c32
2 changed files with 34 additions and 22 deletions

View File

@ -137,6 +137,7 @@ pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
HANDLE events[2]; HANDLE events[2];
int r; int r;
/* Create an event object just once and use it on all future calls */
if (waitevent == INVALID_HANDLE_VALUE) if (waitevent == INVALID_HANDLE_VALUE)
{ {
waitevent = CreateEvent(NULL, TRUE, FALSE, NULL); waitevent = CreateEvent(NULL, TRUE, FALSE, NULL);
@ -150,20 +151,19 @@ pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
(errmsg_internal("could not reset socket waiting event: %i", (int) GetLastError()))); (errmsg_internal("could not reset socket waiting event: %i", (int) GetLastError())));
/* /*
* make sure we don't multiplex this kernel event object with a different * Track whether socket is UDP or not. (NB: most likely, this is both
* socket from a previous call * useless and wrong; there is no reason to think that the behavior of
* WSAEventSelect is different for TCP and UDP.)
*/ */
if (current_socket != s) if (current_socket != s)
{
if (current_socket != -1)
WSAEventSelect(current_socket, waitevent, 0);
isUDP = isDataGram(s); isUDP = isDataGram(s);
}
current_socket = s; current_socket = s;
if (WSAEventSelect(s, waitevent, what) == SOCKET_ERROR) /*
* Attach event to socket. NOTE: we must detach it again before returning,
* since other bits of code may try to attach other events to the socket.
*/
if (WSAEventSelect(s, waitevent, what) != 0)
{ {
TranslateSocketError(); TranslateSocketError();
return 0; return 0;
@ -196,10 +196,14 @@ pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
r = WSASend(s, &buf, 1, &sent, 0, NULL, NULL); r = WSASend(s, &buf, 1, &sent, 0, NULL, NULL);
if (r == 0) /* Completed - means things are fine! */ if (r == 0) /* Completed - means things are fine! */
{
WSAEventSelect(s, NULL, 0);
return 1; return 1;
}
else if (WSAGetLastError() != WSAEWOULDBLOCK) else if (WSAGetLastError() != WSAEWOULDBLOCK)
{ {
TranslateSocketError(); TranslateSocketError();
WSAEventSelect(s, NULL, 0);
return 0; return 0;
} }
} }
@ -210,6 +214,8 @@ pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
else else
r = WaitForMultipleObjectsEx(2, events, FALSE, timeout, TRUE); r = WaitForMultipleObjectsEx(2, events, FALSE, timeout, TRUE);
WSAEventSelect(s, NULL, 0);
if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION) if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION)
{ {
pgwin32_dispatch_queued_signals(); pgwin32_dispatch_queued_signals();
@ -219,7 +225,10 @@ pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
if (r == WAIT_OBJECT_0 + 1) if (r == WAIT_OBJECT_0 + 1)
return 1; return 1;
if (r == WAIT_TIMEOUT) if (r == WAIT_TIMEOUT)
{
errno = EWOULDBLOCK;
return 0; return 0;
}
ereport(ERROR, ereport(ERROR,
(errmsg_internal("unrecognized return value from WaitForMultipleObjects: %i (%i)", r, (int) GetLastError()))); (errmsg_internal("unrecognized return value from WaitForMultipleObjects: %i (%i)", r, (int) GetLastError())));
return 0; return 0;
@ -543,9 +552,12 @@ pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, c
if (writefds && FD_ISSET(sockets[i], writefds)) if (writefds && FD_ISSET(sockets[i], writefds))
flags |= FD_WRITE | FD_CLOSE; flags |= FD_WRITE | FD_CLOSE;
if (WSAEventSelect(sockets[i], events[i], flags) == SOCKET_ERROR) if (WSAEventSelect(sockets[i], events[i], flags) != 0)
{ {
TranslateSocketError(); TranslateSocketError();
/* release already-assigned event objects */
while (--i >= 0)
WSAEventSelect(sockets[i], NULL, 0);
for (i = 0; i < numevents; i++) for (i = 0; i < numevents; i++)
WSACloseEvent(events[i]); WSACloseEvent(events[i]);
return -1; return -1;
@ -565,9 +577,9 @@ pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, c
for (i = 0; i < numevents; i++) for (i = 0; i < numevents; i++)
{ {
ZeroMemory(&resEvents, sizeof(resEvents)); ZeroMemory(&resEvents, sizeof(resEvents));
if (WSAEnumNetworkEvents(sockets[i], events[i], &resEvents) == SOCKET_ERROR) if (WSAEnumNetworkEvents(sockets[i], events[i], &resEvents) != 0)
ereport(FATAL, ereport(FATAL,
(errmsg_internal("failed to enumerate network events: %i", (int) GetLastError()))); (errmsg_internal("failed to enumerate network events: %i", (int) WSAGetLastError())));
/* Read activity? */ /* Read activity? */
if (readfds && FD_ISSET(sockets[i], readfds)) if (readfds && FD_ISSET(sockets[i], readfds))
{ {
@ -594,10 +606,10 @@ pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, c
} }
} }
/* Clean up all handles */ /* Clean up all the event objects */
for (i = 0; i < numevents; i++) for (i = 0; i < numevents; i++)
{ {
WSAEventSelect(sockets[i], events[i], 0); WSAEventSelect(sockets[i], NULL, 0);
WSACloseEvent(events[i]); WSACloseEvent(events[i]);
} }

View File

@ -108,10 +108,11 @@ WaitLatchOrSocket(volatile Latch *latch, pgsocket sock, bool forRead,
numevents = 2; numevents = 2;
if (sock != PGINVALID_SOCKET && (forRead || forWrite)) if (sock != PGINVALID_SOCKET && (forRead || forWrite))
{ {
/* Need an event object to represent events on the socket */
int flags = 0; int flags = 0;
if (forRead) if (forRead)
flags |= FD_READ; flags |= (FD_READ | FD_CLOSE);
if (forWrite) if (forWrite)
flags |= FD_WRITE; flags |= FD_WRITE;
@ -154,11 +155,10 @@ WaitLatchOrSocket(volatile Latch *latch, pgsocket sock, bool forRead,
Assert(sock != PGINVALID_SOCKET); Assert(sock != PGINVALID_SOCKET);
ZeroMemory(&resEvents, sizeof(resEvents)); ZeroMemory(&resEvents, sizeof(resEvents));
if (WSAEnumNetworkEvents(sock, sockevent, &resEvents) == SOCKET_ERROR) if (WSAEnumNetworkEvents(sock, sockevent, &resEvents) != 0)
ereport(FATAL, ereport(FATAL,
(errmsg_internal("failed to enumerate network events: %i", (int) GetLastError()))); (errmsg_internal("failed to enumerate network events: %i", (int) WSAGetLastError())));
if ((forRead && resEvents.lNetworkEvents & (FD_READ | FD_CLOSE)) ||
if ((forRead && resEvents.lNetworkEvents & FD_READ) ||
(forWrite && resEvents.lNetworkEvents & FD_WRITE)) (forWrite && resEvents.lNetworkEvents & FD_WRITE))
result = 2; result = 2;
break; break;
@ -167,10 +167,10 @@ WaitLatchOrSocket(volatile Latch *latch, pgsocket sock, bool forRead,
elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %d", (int) rc); elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %d", (int) rc);
} }
/* Clean up the handle we created for the socket */ /* Clean up the event object we created for the socket */
if (sock != PGINVALID_SOCKET && (forRead || forWrite)) if (sockevent != WSA_INVALID_EVENT)
{ {
WSAEventSelect(sock, sockevent, 0); WSAEventSelect(sock, NULL, 0);
WSACloseEvent(sockevent); WSACloseEvent(sockevent);
} }