Zebediah Figura : server: Properly implement AFD_POLL_RESET.

Alexandre Julliard julliard at winehq.org
Mon Jul 25 16:17:21 CDT 2022


Module: wine
Branch: master
Commit: 7961e00e7429a4cd950a493ab9ff72448808d588
URL:    https://gitlab.winehq.org/wine/wine/-/commit/7961e00e7429a4cd950a493ab9ff72448808d588

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Fri Jul 15 18:44:06 2022 -0500

server: Properly implement AFD_POLL_RESET.

---

 dlls/ws2_32/tests/afd.c  | 17 ++++++++---------
 dlls/ws2_32/tests/sock.c |  2 +-
 server/sock.c            | 34 +++++++++++++++++++++++++++++++---
 3 files changed, 40 insertions(+), 13 deletions(-)

diff --git a/dlls/ws2_32/tests/afd.c b/dlls/ws2_32/tests/afd.c
index eb525c78c54..21e7a50aef3 100644
--- a/dlls/ws2_32/tests/afd.c
+++ b/dlls/ws2_32/tests/afd.c
@@ -162,8 +162,7 @@ static void check_poll_(int line, SOCKET s, HANDLE event, int mask, int expect,
     ok_(__FILE__, line)(out_params.count == 1, "got count %u\n", out_params.count);
     ok_(__FILE__, line)(out_params.sockets[0].socket == s, "got socket %#Ix\n", out_params.sockets[0].socket);
     todo_wine_if (todo) ok_(__FILE__, line)(out_params.sockets[0].flags == expect, "got flags %#x\n", out_params.sockets[0].flags);
-    todo_wine_if (expect & AFD_POLL_RESET)
-        ok_(__FILE__, line)(!out_params.sockets[0].status, "got status %#x\n", out_params.sockets[0].status);
+    ok_(__FILE__, line)(!out_params.sockets[0].status, "got status %#x\n", out_params.sockets[0].status);
 }
 
 static void test_poll(void)
@@ -1407,10 +1406,10 @@ static void test_poll_reset(void)
     ok(io.Information == offsetof(struct afd_poll_params, sockets[1]), "got %#Ix\n", io.Information);
     ok(out_params->count == 1, "got count %u\n", out_params->count);
     ok(out_params->sockets[0].socket == client, "got socket %#Ix\n", out_params->sockets[0].socket);
-    todo_wine ok(out_params->sockets[0].flags == AFD_POLL_RESET, "got flags %#x\n", out_params->sockets[0].flags);
-    todo_wine ok(!out_params->sockets[0].status, "got status %#x\n", out_params->sockets[0].status);
+    ok(out_params->sockets[0].flags == AFD_POLL_RESET, "got flags %#x\n", out_params->sockets[0].flags);
+    ok(!out_params->sockets[0].status, "got status %#x\n", out_params->sockets[0].status);
 
-    check_poll_todo(client, event, AFD_POLL_WRITE | AFD_POLL_CONNECT | AFD_POLL_RESET);
+    check_poll(client, event, AFD_POLL_WRITE | AFD_POLL_CONNECT | AFD_POLL_RESET);
 
     closesocket(client);
     CloseHandle(event);
@@ -2042,9 +2041,9 @@ static void test_get_events_reset(void)
     ret = NtDeviceIoControlFile((HANDLE)client, NULL, NULL, NULL, &io,
             IOCTL_AFD_GET_EVENTS, NULL, 0, &params, sizeof(params));
     ok(!ret, "got %#x\n", ret);
-    todo_wine ok(params.flags == (AFD_POLL_RESET | AFD_POLL_CONNECT | AFD_POLL_WRITE), "got flags %#x\n", params.flags);
+    ok(params.flags == (AFD_POLL_RESET | AFD_POLL_CONNECT | AFD_POLL_WRITE), "got flags %#x\n", params.flags);
     for (i = 0; i < ARRAY_SIZE(params.status); ++i)
-        todo_wine_if (i == AFD_POLL_BIT_HUP) ok(!params.status[i], "got status[%u] %#x\n", i, params.status[i]);
+        ok(!params.status[i], "got status[%u] %#x\n", i, params.status[i]);
 
     closesocket(client);
 
@@ -2060,9 +2059,9 @@ static void test_get_events_reset(void)
     ret = NtDeviceIoControlFile((HANDLE)server, NULL, NULL, NULL, &io,
             IOCTL_AFD_GET_EVENTS, NULL, 0, &params, sizeof(params));
     ok(!ret, "got %#x\n", ret);
-    todo_wine ok(params.flags == (AFD_POLL_RESET | AFD_POLL_WRITE), "got flags %#x\n", params.flags);
+    ok(params.flags == (AFD_POLL_RESET | AFD_POLL_WRITE), "got flags %#x\n", params.flags);
     for (i = 0; i < ARRAY_SIZE(params.status); ++i)
-        todo_wine_if (i == AFD_POLL_BIT_HUP) ok(!params.status[i], "got status[%u] %#x\n", i, params.status[i]);
+        ok(!params.status[i], "got status[%u] %#x\n", i, params.status[i]);
 
     closesocket(server);
 
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 576fe1cee6a..3e6faaffa4c 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -12861,7 +12861,7 @@ static void test_tcp_reset(void)
     len = sizeof(error);
     ret = getsockopt(client, SOL_SOCKET, SO_ERROR, (char *)&error, &len);
     ok(!ret, "got error %u\n", WSAGetLastError());
-    todo_wine ok(!error, "got error %u\n", error);
+    ok(!error, "got error %u\n", error);
 
     wsabuf.buf = buffer;
     wsabuf.len = sizeof(buffer);
diff --git a/server/sock.c b/server/sock.c
index 53553ab8ee7..7d7e470be28 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -232,6 +232,7 @@ struct sock
     unsigned int        aborted : 1; /* did we get a POLLERR or irregular POLLHUP? */
     unsigned int        nonblocking : 1; /* is the socket nonblocking? */
     unsigned int        bound : 1;   /* is the socket bound? */
+    unsigned int        reset : 1;   /* did we get a TCP reset? */
 };
 
 static void sock_dump( struct object *obj, int verbose );
@@ -667,7 +668,12 @@ static inline int sock_error( struct sock *sock )
 
     case SOCK_CONNECTED:
     case SOCK_CONNECTIONLESS:
-        if (error)
+        if (error == ECONNRESET || error == EPIPE)
+        {
+            sock->reset = 1;
+            error = 0;
+        }
+        else if (error)
             sock->errors[AFD_POLL_BIT_HUP] = error;
         else
             error = sock->errors[AFD_POLL_BIT_HUP];
@@ -897,6 +903,8 @@ static int get_poll_flags( struct sock *sock, int event )
         flags |= AFD_POLL_HUP;
     if (event & POLLERR)
         flags |= AFD_POLL_CONNECT_ERR;
+    if (sock->reset)
+        flags |= AFD_POLL_RESET;
 
     return flags;
 }
@@ -1081,6 +1089,15 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error )
             async_terminate( sock->connect_req->async, status );
     }
 
+    if (sock->reset)
+    {
+        async_wake_up( &sock->read_q, STATUS_CONNECTION_RESET );
+        async_wake_up( &sock->write_q, STATUS_CONNECTION_RESET );
+
+        if (sock->accept_recv_req && sock->accept_recv_req->iosb->status == STATUS_PENDING)
+            async_terminate( sock->accept_recv_req->async, STATUS_CONNECTION_RESET );
+    }
+
     return event;
 }
 
@@ -1116,6 +1133,9 @@ static void sock_dispatch_events( struct sock *sock, enum connection_state prevs
 
     case SOCK_CONNECTED:
     case SOCK_CONNECTIONLESS:
+        if (sock->reset)
+            post_socket_event( sock, AFD_POLL_BIT_RESET );
+
         if (event & POLLIN)
             post_socket_event( sock, AFD_POLL_BIT_READ );
 
@@ -1171,6 +1191,9 @@ static void sock_poll_event( struct fd *fd, int event )
 
     case SOCK_CONNECTED:
     case SOCK_CONNECTIONLESS:
+        if (sock->reset)
+            event &= ~(POLLIN | POLLERR | POLLHUP);
+
         if (sock->type == WS_SOCK_STREAM && (event & POLLIN))
         {
             char dummy;
@@ -1189,7 +1212,11 @@ static void sock_poll_event( struct fd *fd, int event )
                 event &= ~POLLIN;
                 /* EAGAIN can happen if an async recv() falls between the server's poll()
                    call and the invocation of this routine */
-                if ( errno != EAGAIN )
+                if (errno == ECONNRESET || errno == EPIPE)
+                {
+                    sock->reset = 1;
+                }
+                else if (errno != EAGAIN)
                 {
                     error = errno;
                     event |= POLLERR;
@@ -1312,7 +1339,7 @@ static int sock_get_poll_events( struct fd *fd )
             return -1;
         }
 
-        if (sock->aborted)
+        if (sock->aborted || sock->reset)
             return -1;
 
         if (sock->accept_recv_req)
@@ -1517,6 +1544,7 @@ static struct sock *create_socket(void)
     sock->aborted = 0;
     sock->nonblocking = 0;
     sock->bound = 0;
+    sock->reset = 0;
     sock->rcvbuf = 0;
     sock->sndbuf = 0;
     sock->rcvtimeo = 0;




More information about the wine-cvs mailing list