Zebediah Figura : server: Use separate fields to track socket shutdown state.

Alexandre Julliard julliard at winehq.org
Fri Jun 11 15:31:29 CDT 2021


Module: wine
Branch: master
Commit: 5eaba82a7719e1f059ef5636aee37c4e49f28626
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=5eaba82a7719e1f059ef5636aee37c4e49f28626

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Thu Jun 10 19:36:25 2021 -0500

server: Use separate fields to track socket shutdown state.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 server/sock.c | 59 ++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 38 insertions(+), 21 deletions(-)

diff --git a/server/sock.c b/server/sock.c
index 7941ed856d3..4cd84637baf 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -172,6 +172,8 @@ struct sock
     struct list         accept_list; /* list of pending accept requests */
     struct accept_req  *accept_recv_req; /* pending accept-into request which will recv on this socket */
     struct connect_req *connect_req; /* pending connection request */
+    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        nonblocking : 1; /* is the socket nonblocking? */
 };
@@ -781,9 +783,9 @@ 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->state & FD_READ))
+        if (sock->rd_shutdown)
             async_wake_up( &sock->read_q, status );
-        if (!(sock->state & FD_WRITE))
+        if (sock->wr_shutdown)
             async_wake_up( &sock->write_q, status );
 
         LIST_FOR_EACH_ENTRY_SAFE( req, next, &sock->accept_list, struct accept_req, entry )
@@ -869,7 +871,7 @@ static void sock_poll_event( struct fd *fd, int event )
         else if (event & POLLOUT)
         {
             /* we got connected */
-            sock->state |= FD_WINE_CONNECTED|FD_READ|FD_WRITE;
+            sock->state |= FD_WINE_CONNECTED;
             sock->state &= ~FD_CONNECT;
             sock->connect_time = current_time;
         }
@@ -911,12 +913,12 @@ static void sock_poll_event( struct fd *fd, int event )
             }
         }
 
-        if ( (hangup_seen || event & (POLLHUP|POLLERR)) && (sock->state & (FD_READ|FD_WRITE)) )
+        if ((hangup_seen || event & (POLLHUP | POLLERR)) && (!sock->rd_shutdown || !sock->wr_shutdown))
         {
             error = error ? error : sock_error( fd );
             if ( (event & POLLERR) || ( sock_shutdown_type == SOCK_SHUTDOWN_EOF && (event & POLLHUP) ))
-                sock->state &= ~FD_WRITE;
-            sock->state &= ~FD_READ;
+                sock->wr_shutdown = 1;
+            sock->rd_shutdown = 1;
 
             if (debug_level)
                 fprintf(stderr, "socket %p aborted by error %d, event: %x\n", sock, error, event);
@@ -969,7 +971,6 @@ static int sock_get_poll_events( struct fd *fd )
 {
     struct sock *sock = get_fd_user( fd );
     unsigned int mask = sock->mask & ~sock->reported_events;
-    unsigned int smask = sock->state & mask;
     struct poll_req *req;
     int ev = 0;
 
@@ -996,7 +997,12 @@ static int sock_get_poll_events( struct fd *fd )
     {
         if (async_waiting( &sock->read_q )) ev |= POLLIN | POLLPRI;
     }
-    else if (smask & FD_READ || (sock->state & FD_WINE_LISTENING && mask & FD_ACCEPT))
+    else if (sock->state & FD_WINE_LISTENING)
+    {
+        if (mask & FD_ACCEPT)
+            ev |= POLLIN;
+    }
+    else if (!sock->rd_shutdown && (mask & FD_READ))
         ev |= POLLIN | POLLPRI;
     /* We use POLLIN with 0 bytes recv() as FD_CLOSE indication for stream sockets. */
     else if (sock->type == WS_SOCK_STREAM && (mask & FD_CLOSE) && !(sock->reported_events & FD_READ))
@@ -1006,7 +1012,7 @@ static int sock_get_poll_events( struct fd *fd )
     {
         if (async_waiting( &sock->write_q )) ev |= POLLOUT;
     }
-    else if (smask & FD_WRITE)
+    else if (!sock->wr_shutdown && (mask & FD_WRITE))
         ev |= POLLOUT;
 
     LIST_FOR_EACH_ENTRY( req, &poll_list, struct poll_req, entry )
@@ -1039,18 +1045,30 @@ static void sock_queue_async( struct fd *fd, struct async *async, int type, int
     switch (type)
     {
     case ASYNC_TYPE_READ:
+        if (sock->rd_shutdown)
+        {
+            set_error( STATUS_PIPE_DISCONNECTED );
+            return;
+        }
         queue = &sock->read_q;
         break;
+
     case ASYNC_TYPE_WRITE:
+        if (sock->wr_shutdown)
+        {
+            set_error( STATUS_PIPE_DISCONNECTED );
+            return;
+        }
         queue = &sock->write_q;
         break;
+
     default:
         set_error( STATUS_INVALID_PARAMETER );
         return;
     }
 
-    if ( ( !( sock->state & (FD_READ|FD_CONNECT|FD_WINE_LISTENING) ) && type == ASYNC_TYPE_READ  ) ||
-         ( !( sock->state & (FD_WRITE|FD_CONNECT) ) && type == ASYNC_TYPE_WRITE ) )
+    if ( ( !( sock->state & (FD_CONNECT|FD_WINE_LISTENING) ) && type == ASYNC_TYPE_READ  ) ||
+         ( !( sock->state & (FD_CONNECT) ) && type == ASYNC_TYPE_WRITE ) )
     {
         set_error( STATUS_PIPE_DISCONNECTED );
         return;
@@ -1180,6 +1198,8 @@ static struct sock *create_socket(void)
     sock->ifchange_obj = NULL;
     sock->accept_recv_req = NULL;
     sock->connect_req = NULL;
+    sock->rd_shutdown = 0;
+    sock->wr_shutdown = 0;
     sock->wr_shutdown_pending = 0;
     sock->nonblocking = 0;
     init_async_queue( &sock->read_q );
@@ -1339,7 +1359,6 @@ static int init_socket( struct sock *sock, int family, int type, int protocol, u
     }
 #endif
 
-    sock->state  = (type != SOCK_STREAM) ? (FD_READ|FD_WRITE) : 0;
     sock->flags  = flags;
     sock->proto  = protocol;
     sock->type   = type;
@@ -1404,7 +1423,7 @@ static struct sock *accept_socket( struct sock *sock )
         }
 
         /* newly created socket gets the same properties of the listening socket */
-        acceptsock->state  = FD_WINE_CONNECTED|FD_READ|FD_WRITE;
+        acceptsock->state   = FD_WINE_CONNECTED;
         acceptsock->nonblocking = sock->nonblocking;
         acceptsock->mask    = sock->mask;
         acceptsock->proto   = sock->proto;
@@ -1458,7 +1477,7 @@ static int accept_into_socket( struct sock *sock, struct sock *acceptsock )
             return FALSE;
     }
 
-    acceptsock->state  |= FD_WINE_CONNECTED|FD_READ|FD_WRITE;
+    acceptsock->state |= FD_WINE_CONNECTED;
     acceptsock->pending_events = 0;
     acceptsock->reported_events = 0;
     acceptsock->proto   = sock->proto;
@@ -1808,7 +1827,7 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
 
         if (!ret)
         {
-            sock->state |= FD_WINE_CONNECTED | FD_READ | FD_WRITE;
+            sock->state |= FD_WINE_CONNECTED;
             sock->state &= ~FD_CONNECT;
 
             if (!send_len) return 1;
@@ -1866,11 +1885,11 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
 
         if (how != SD_SEND)
         {
-            sock->state &= ~FD_READ;
+            sock->rd_shutdown = 1;
         }
         if (how != SD_RECEIVE)
         {
-            sock->state &= ~FD_WRITE;
+            sock->wr_shutdown = 1;
             if (list_empty( &sock->write_q.queue ))
                 shutdown( unix_fd, SHUT_WR );
             else
@@ -2462,8 +2481,7 @@ DECL_HANDLER(recv_socket)
         status = STATUS_PENDING;
     }
 
-    /* are we shut down? */
-    if (status == STATUS_PENDING && !(sock->state & FD_READ)) status = STATUS_PIPE_DISCONNECTED;
+    if (status == STATUS_PENDING && sock->rd_shutdown) status = STATUS_PIPE_DISCONNECTED;
 
     sock->pending_events &= ~(req->oob ? FD_OOB : FD_READ);
     sock->reported_events &= ~(req->oob ? FD_OOB : FD_READ);
@@ -2567,8 +2585,7 @@ DECL_HANDLER(send_socket)
         status = STATUS_PENDING;
     }
 
-    /* are we shut down? */
-    if (status == STATUS_PENDING && !(sock->state & FD_WRITE)) status = STATUS_PIPE_DISCONNECTED;
+    if (status == STATUS_PENDING && sock->wr_shutdown) status = STATUS_PIPE_DISCONNECTED;
 
     if ((async = create_request_async( fd, get_fd_comp_flags( fd ), &req->async )))
     {




More information about the wine-cvs mailing list