Skip to content

Commit fe3ae8e

Browse files
committed
event: handle socket events more precisely
This adjusts the socket event to correct a potential spurious wakeup which can incorrectly mark the socket as closed. When working with a `SOCK_STREAM` socket, `FIONREAD` returns the total amount of data that can be read in a single receive operation. Normally, this is the same amount of data queued on the socket, but this is not guaranteed as a data-stream is byte-oriented. Additionally, a read on a separate thread may have drained the data between the event trigger and the ioctl to read the available bytes. Only wake up the handler if there are bytes to read. In order to differentiate between the trigger for a close event and a read-event, we explicitly check the close and the read or write event. This allows waking the handlers one last time after a socket is closed.
1 parent 35f5c96 commit fe3ae8e

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

src/event/event_windows.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -359,22 +359,22 @@ _dispatch_socket_callback(PTP_CALLBACK_INSTANCE inst, void *context,
359359
DWORD dwBytesAvailable = 1;
360360
if (lNetworkEvents & FD_CLOSE) {
361361
dwBytesAvailable = 0;
362-
// Post to all registered read and write handlers
363-
lNetworkEvents |= FD_READ | FD_WRITE;
364362
} else if (lNetworkEvents & FD_READ) {
365363
ioctlsocket(sock, FIONREAD, &dwBytesAvailable);
366364
}
367-
if (lNetworkEvents & FD_READ) {
365+
if ((lNetworkEvents & FD_CLOSE) ||
366+
((lNetworkEvents & FD_READ) && (dwBytesAvailable > 0))) {
368367
_dispatch_muxnote_retain(dmn);
369368
if (!PostQueuedCompletionStatus(hPort, dwBytesAvailable,
370369
(ULONG_PTR)DISPATCH_PORT_SOCKET_READ, (LPOVERLAPPED)dmn)) {
371370
DISPATCH_INTERNAL_CRASH(GetLastError(),
372371
"PostQueuedCompletionStatus");
373372
}
374373
}
375-
if (lNetworkEvents & FD_WRITE) {
374+
if ((lNetworkEvents & FD_CLOSE) || (lNetworkEvents & FD_WRITE)) {
376375
_dispatch_muxnote_retain(dmn);
377-
if (!PostQueuedCompletionStatus(hPort, dwBytesAvailable,
376+
if (!PostQueuedCompletionStatus(hPort,
377+
lNetworkEvents & FD_CLOSE ? 0 : 1,
378378
(ULONG_PTR)DISPATCH_PORT_SOCKET_WRITE, (LPOVERLAPPED)dmn)) {
379379
DISPATCH_INTERNAL_CRASH(GetLastError(),
380380
"PostQueuedCompletionStatus");

0 commit comments

Comments
 (0)