[PATCH 2/6] server: Separate SD_RECEIVE and hangup conditions.

Zebediah Figura zfigura at codeweavers.com
Sat Jul 24 18:54:28 CDT 2021


This patch does result in one functional change: if we are selecting for
AFD_POLL_READ on a socket which has had SD_RECEIVE and there are no asyncs, we
will now respond to POLLIN instead of ignoring it. Neither this nor the previous
behaviour matches Windows, which instead puts the socket into an aborted state
and sends RST to the peer if any data is received after SD_RECEIVE or if
SD_RECEIVE is done while there is pending data.

Apart from this there is no functional change, as the places where rd_shutdown
alone is checked can't be reached if there was a hangup. It is instead for
semantic clarity.

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 server/sock.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/server/sock.c b/server/sock.c
index e5b0e81ead2..85ea019ad92 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -214,6 +214,7 @@ struct sock
     unsigned int        rd_shutdown : 1; /* is the read end shut down? */
     unsigned int        wr_shutdown : 1; /* is the write end shut down? */
     unsigned int        wr_shutdown_pending : 1; /* is a write shutdown pending? */
+    unsigned int        hangup : 1;  /* has the read end received a hangup? */
     unsigned int        nonblocking : 1; /* is the socket nonblocking? */
     unsigned int        bound : 1;   /* is the socket bound? */
 };
@@ -930,7 +931,7 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error )
         int status = sock_get_ntstatus( error );
         struct accept_req *req, *next;
 
-        if (sock->rd_shutdown)
+        if (sock->rd_shutdown || sock->hangup)
             async_wake_up( &sock->read_q, status );
         if (sock->wr_shutdown)
             async_wake_up( &sock->write_q, status );
@@ -1072,15 +1073,17 @@ static void sock_poll_event( struct fd *fd, int event )
             }
         }
 
-        if ((hangup_seen || event & (POLLHUP | POLLERR)) && (!sock->rd_shutdown || !sock->wr_shutdown))
+        if (hangup_seen || (sock_shutdown_type == SOCK_SHUTDOWN_POLLHUP && (event & POLLHUP)))
+        {
+            sock->hangup = 1;
+        }
+        else if (event & (POLLHUP | POLLERR))
         {
-            error = error ? error : sock_error( fd );
-            if ( (event & POLLERR) || ( sock_shutdown_type == SOCK_SHUTDOWN_EOF && (event & POLLHUP) ))
-                sock->wr_shutdown = 1;
             sock->rd_shutdown = 1;
+            sock->wr_shutdown = 1;
 
             if (debug_level)
-                fprintf(stderr, "socket %p aborted by error %d, event: %x\n", sock, error, event);
+                fprintf( stderr, "socket %p aborted by error %d, event %#x\n", sock, error, event );
         }
 
         if (hangup_seen)
@@ -1168,7 +1171,9 @@ static int sock_get_poll_events( struct fd *fd )
         }
         else
         {
-            if (!sock->rd_shutdown)
+            /* Don't ask for POLLIN if we got a hangup. We won't receive more
+             * data anyway, but we will get POLLIN if SOCK_SHUTDOWN_EOF. */
+            if (!sock->hangup)
             {
                 if (mask & AFD_POLL_READ)
                     ev |= POLLIN;
@@ -1380,6 +1385,7 @@ static struct sock *create_socket(void)
     sock->rd_shutdown = 0;
     sock->wr_shutdown = 0;
     sock->wr_shutdown_pending = 0;
+    sock->hangup = 0;
     sock->nonblocking = 0;
     sock->bound = 0;
     sock->rcvbuf = 0;
-- 
2.30.2




More information about the wine-devel mailing list