Module: wine
Branch: master
Commit: 25f8698fcdb1907010bb34169c0d3ecf46b3bf51
URL: https://gitlab.winehq.org/wine/wine/-/commit/25f8698fcdb1907010bb34169c0d3e…
Author: Zebediah Figura <zfigura(a)codeweavers.com>
Date: Tue Oct 31 12:22:31 2023 -0500
server: Only set sock->event when the event is first noticed.
Do not set it every time another event is polled.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55838
---
dlls/ws2_32/tests/sock.c | 2 +-
server/sock.c | 36 ++++++++++++++++++++++--------------
2 files changed, 23 insertions(+), 15 deletions(-)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 5e22496e6ef..f9cc1482c41 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -14025,7 +14025,7 @@ static void test_select_after_WSAEventSelect(void)
check_poll(client, POLLRDNORM | POLLWRNORM);
ret = WaitForSingleObject(event, 0);
- todo_wine ok(ret == WAIT_TIMEOUT, "got %d\n", ret);
+ ok(ret == WAIT_TIMEOUT, "got %d\n", ret);
CloseHandle(event);
closesocket(server);
diff --git a/server/sock.c b/server/sock.c
index 45a4955d603..f774cded733 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -787,18 +787,11 @@ static unsigned int afd_poll_flag_to_win32( unsigned int flags )
return ret;
}
-/* wake anybody waiting on the socket event or send the associated message */
-static void sock_wake_up( struct sock *sock )
+static void post_sock_messages( struct sock *sock )
{
unsigned int events = sock->pending_events & sock->mask;
int i;
- if (sock->event)
- {
- if (debug_level) fprintf(stderr, "signalling events %x ptr %p\n", events, sock->event );
- if (events)
- set_event( sock->event );
- }
if (sock->window)
{
if (debug_level) fprintf(stderr, "signalling events %x win %08x\n", events, sock->window );
@@ -1285,6 +1278,9 @@ static void post_socket_event( struct sock *sock, enum afd_poll_bit event_bit )
{
sock->pending_events |= event;
sock->reported_events |= event;
+
+ if ((sock->mask & event) && sock->event)
+ set_event( sock->event );
}
}
@@ -1329,7 +1325,7 @@ static void sock_dispatch_events( struct sock *sock, enum connection_state prevs
break;
}
- sock_wake_up( sock );
+ post_sock_messages( sock );
}
static void sock_poll_event( struct fd *fd, int event )
@@ -2858,11 +2854,23 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
sock->nonblocking = 1;
sock_reselect( sock );
- /* Explicitly wake the socket up if the mask causes it to become
- * signaled. Note that reselecting isn't enough, since we might already
- * have had events recorded in sock->reported_events and we don't want
- * to select for them again. */
- sock_wake_up( sock );
+
+ /* Explicitly wake the socket up if the mask matches pending_events.
+ *
+ * The logic here is a bit surprising. We always set the event if the
+ * socket has events that haven't been consumed by
+ * WSAEnumNetworkEvents() yet, including if WSAEventSelect() is called
+ * multiple times without consuming the events.
+ * However, once the events are consumed by WSAEnumNetworkEvents(), we
+ * don't set the event again (even though e.g. data is still available)
+ * until a "reset" call (i.e. that clears reported_events). */
+
+ if (event && (sock->pending_events & mask))
+ {
+ if (debug_level) fprintf( stderr, "signalling pending events %#x due to event select\n",
+ sock->pending_events & mask );
+ set_event( event );
+ }
return;
}