Skip to content

Commit ed597d0

Browse files
committed
Back-patch fixes for some issues in our Windows socket code into 9.1.
This is a backport of commit b85427f. 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.
1 parent 180ce0a commit ed597d0

File tree

2 files changed

+34
-22
lines changed

2 files changed

+34
-22
lines changed

src/backend/port/win32/socket.c

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
137137
HANDLE events[2];
138138
int r;
139139

140+
/* Create an event object just once and use it on all future calls */
140141
if (waitevent == INVALID_HANDLE_VALUE)
141142
{
142143
waitevent = CreateEvent(NULL, TRUE, FALSE, NULL);
@@ -150,20 +151,19 @@ pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
150151
(errmsg_internal("could not reset socket waiting event: %i", (int) GetLastError())));
151152

152153
/*
153-
* make sure we don't multiplex this kernel event object with a different
154-
* socket from a previous call
154+
* Track whether socket is UDP or not. (NB: most likely, this is both
155+
* useless and wrong; there is no reason to think that the behavior of
156+
* WSAEventSelect is different for TCP and UDP.)
155157
*/
156-
157158
if (current_socket != s)
158-
{
159-
if (current_socket != -1)
160-
WSAEventSelect(current_socket, waitevent, 0);
161159
isUDP = isDataGram(s);
162-
}
163-
164160
current_socket = s;
165161

166-
if (WSAEventSelect(s, waitevent, what) == SOCKET_ERROR)
162+
/*
163+
* Attach event to socket. NOTE: we must detach it again before returning,
164+
* since other bits of code may try to attach other events to the socket.
165+
*/
166+
if (WSAEventSelect(s, waitevent, what) != 0)
167167
{
168168
TranslateSocketError();
169169
return 0;
@@ -196,10 +196,14 @@ pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
196196

197197
r = WSASend(s, &buf, 1, &sent, 0, NULL, NULL);
198198
if (r == 0) /* Completed - means things are fine! */
199+
{
200+
WSAEventSelect(s, NULL, 0);
199201
return 1;
202+
}
200203
else if (WSAGetLastError() != WSAEWOULDBLOCK)
201204
{
202205
TranslateSocketError();
206+
WSAEventSelect(s, NULL, 0);
203207
return 0;
204208
}
205209
}
@@ -210,6 +214,8 @@ pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
210214
else
211215
r = WaitForMultipleObjectsEx(2, events, FALSE, timeout, TRUE);
212216

217+
WSAEventSelect(s, NULL, 0);
218+
213219
if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION)
214220
{
215221
pgwin32_dispatch_queued_signals();
@@ -219,7 +225,10 @@ pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
219225
if (r == WAIT_OBJECT_0 + 1)
220226
return 1;
221227
if (r == WAIT_TIMEOUT)
228+
{
229+
errno = EWOULDBLOCK;
222230
return 0;
231+
}
223232
ereport(ERROR,
224233
(errmsg_internal("unrecognized return value from WaitForMultipleObjects: %i (%i)", r, (int) GetLastError())));
225234
return 0;
@@ -543,9 +552,12 @@ pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, c
543552
if (writefds && FD_ISSET(sockets[i], writefds))
544553
flags |= FD_WRITE | FD_CLOSE;
545554

546-
if (WSAEventSelect(sockets[i], events[i], flags) == SOCKET_ERROR)
555+
if (WSAEventSelect(sockets[i], events[i], flags) != 0)
547556
{
548557
TranslateSocketError();
558+
/* release already-assigned event objects */
559+
while (--i >= 0)
560+
WSAEventSelect(sockets[i], NULL, 0);
549561
for (i = 0; i < numevents; i++)
550562
WSACloseEvent(events[i]);
551563
return -1;
@@ -565,9 +577,9 @@ pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, c
565577
for (i = 0; i < numevents; i++)
566578
{
567579
ZeroMemory(&resEvents, sizeof(resEvents));
568-
if (WSAEnumNetworkEvents(sockets[i], events[i], &resEvents) == SOCKET_ERROR)
580+
if (WSAEnumNetworkEvents(sockets[i], events[i], &resEvents) != 0)
569581
ereport(FATAL,
570-
(errmsg_internal("failed to enumerate network events: %i", (int) GetLastError())));
582+
(errmsg_internal("failed to enumerate network events: %i", (int) WSAGetLastError())));
571583
/* Read activity? */
572584
if (readfds && FD_ISSET(sockets[i], readfds))
573585
{
@@ -594,10 +606,10 @@ pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, c
594606
}
595607
}
596608

597-
/* Clean up all handles */
609+
/* Clean up all the event objects */
598610
for (i = 0; i < numevents; i++)
599611
{
600-
WSAEventSelect(sockets[i], events[i], 0);
612+
WSAEventSelect(sockets[i], NULL, 0);
601613
WSACloseEvent(events[i]);
602614
}
603615

src/backend/port/win32_latch.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,11 @@ WaitLatchOrSocket(volatile Latch *latch, pgsocket sock, bool forRead,
108108
numevents = 2;
109109
if (sock != PGINVALID_SOCKET && (forRead || forWrite))
110110
{
111+
/* Need an event object to represent events on the socket */
111112
int flags = 0;
112113

113114
if (forRead)
114-
flags |= FD_READ;
115+
flags |= (FD_READ | FD_CLOSE);
115116
if (forWrite)
116117
flags |= FD_WRITE;
117118

@@ -154,11 +155,10 @@ WaitLatchOrSocket(volatile Latch *latch, pgsocket sock, bool forRead,
154155
Assert(sock != PGINVALID_SOCKET);
155156

156157
ZeroMemory(&resEvents, sizeof(resEvents));
157-
if (WSAEnumNetworkEvents(sock, sockevent, &resEvents) == SOCKET_ERROR)
158+
if (WSAEnumNetworkEvents(sock, sockevent, &resEvents) != 0)
158159
ereport(FATAL,
159-
(errmsg_internal("failed to enumerate network events: %i", (int) GetLastError())));
160-
161-
if ((forRead && resEvents.lNetworkEvents & FD_READ) ||
160+
(errmsg_internal("failed to enumerate network events: %i", (int) WSAGetLastError())));
161+
if ((forRead && resEvents.lNetworkEvents & (FD_READ | FD_CLOSE)) ||
162162
(forWrite && resEvents.lNetworkEvents & FD_WRITE))
163163
result = 2;
164164
break;
@@ -167,10 +167,10 @@ WaitLatchOrSocket(volatile Latch *latch, pgsocket sock, bool forRead,
167167
elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %d", (int) rc);
168168
}
169169

170-
/* Clean up the handle we created for the socket */
171-
if (sock != PGINVALID_SOCKET && (forRead || forWrite))
170+
/* Clean up the event object we created for the socket */
171+
if (sockevent != WSA_INVALID_EVENT)
172172
{
173-
WSAEventSelect(sock, sockevent, 0);
173+
WSAEventSelect(sock, NULL, 0);
174174
WSACloseEvent(sockevent);
175175
}
176176

0 commit comments

Comments
 (0)