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:
parent
180ce0af33
commit
ed597d0c32
@ -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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user