Zebediah Figura : server: Use sock_poll_event() in poll_socket().

Alexandre Julliard julliard at winehq.org
Wed Jul 20 15:55:32 CDT 2022


Module: wine
Branch: master
Commit: 236476417ac6777951d1cfc26c0393bff2a64c23
URL:    https://gitlab.winehq.org/wine/wine/-/commit/236476417ac6777951d1cfc26c0393bff2a64c23

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Wed Apr 27 19:25:20 2022 -0500

server: Use sock_poll_event() in poll_socket().

In multiple cases errors may be reported only once by the host socket
implementation, but should persist for Windows sockets. These cases are
currently not handled by poll_socket().

poll_socket() also does not include logic for filtering out events when asyncs
are queued or alerted on the relevant socket.

Hence, instead of duplicating more logic, remove the logic already duplicated,
and just call sock_poll_event(), so that there is one central place where events
are translated.

Mark the currently active poll async with a special "pending" field so that
poll_socket() does not attempt to complete it before all sockets are checked.

---

 server/sock.c | 53 +++++++++++++++++------------------------------------
 1 file changed, 17 insertions(+), 36 deletions(-)

diff --git a/server/sock.c b/server/sock.c
index 95335df8fd3..b96f81a0ea8 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -124,6 +124,7 @@ struct poll_req
     struct timeout_user *timeout;
     timeout_t orig_timeout;
     int exclusive;
+    int pending;
     unsigned int count;
     struct
     {
@@ -981,8 +982,11 @@ static void complete_async_polls( struct sock *sock, int event, int error )
             req->sockets[i].flags = req->sockets[i].mask & flags;
             req->sockets[i].status = sock_get_ntstatus( error );
 
-            complete_async_poll( req, STATUS_SUCCESS );
-            break;
+            if (req->pending)
+            {
+                complete_async_poll( req, STATUS_SUCCESS );
+                break;
+            }
         }
     }
 }
@@ -3002,32 +3006,6 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
     }
 }
 
-static int poll_single_socket( struct sock *sock, int mask )
-{
-    struct pollfd pollfd;
-
-    pollfd.fd = get_unix_fd( sock->fd );
-    pollfd.events = poll_flags_from_afd( sock, mask );
-    if (pollfd.events < 0 || poll( &pollfd, 1, 0 ) < 0)
-        return 0;
-
-    if (sock->state == SOCK_CONNECTING && (pollfd.revents & (POLLERR | POLLHUP)))
-        pollfd.revents &= ~POLLOUT;
-
-    if ((mask & AFD_POLL_HUP) && (pollfd.revents & POLLIN) && sock->type == WS_SOCK_STREAM)
-    {
-        char dummy;
-
-        if (!recv( get_unix_fd( sock->fd ), &dummy, 1, MSG_PEEK ))
-        {
-            pollfd.revents &= ~POLLIN;
-            pollfd.revents |= POLLHUP;
-        }
-    }
-
-    return get_poll_flags( sock, pollfd.revents ) & mask;
-}
-
 static void handle_exclusive_poll(struct poll_req *req)
 {
     unsigned int i;
@@ -3065,6 +3043,7 @@ static void poll_socket( struct sock *poll_sock, struct async *async, int exclus
         return;
 
     req->timeout = NULL;
+    req->pending = 0;
     if (timeout && timeout != TIMEOUT_INFINITE &&
         !(req->timeout = add_timeout_user( timeout, async_poll_timeout, req )))
     {
@@ -3103,26 +3082,28 @@ static void poll_socket( struct sock *poll_sock, struct async *async, int exclus
     {
         struct sock *sock = req->sockets[i].sock;
         int mask = req->sockets[i].mask;
-        int flags = poll_single_socket( sock, mask );
+        struct pollfd pollfd;
 
-        if (flags)
-        {
-            signaled = TRUE;
-            req->sockets[i].flags = flags;
-            req->sockets[i].status = sock_get_ntstatus( sock_error( sock ) );
-        }
+        pollfd.fd = get_unix_fd( sock->fd );
+        pollfd.events = poll_flags_from_afd( sock, mask );
+        if (pollfd.events >= 0 && poll( &pollfd, 1, 0 ) >= 0)
+            sock_poll_event( sock->fd, pollfd.revents );
 
         /* FIXME: do other error conditions deserve a similar treatment? */
         if (sock->state != SOCK_CONNECTING && sock->errors[AFD_POLL_BIT_CONNECT_ERR] && (mask & AFD_POLL_CONNECT_ERR))
         {
-            signaled = TRUE;
             req->sockets[i].flags |= AFD_POLL_CONNECT_ERR;
             req->sockets[i].status = sock_get_ntstatus( sock->errors[AFD_POLL_BIT_CONNECT_ERR] );
         }
+
+        if (req->sockets[i].flags)
+            signaled = TRUE;
     }
 
     if (!timeout || signaled)
         complete_async_poll( req, STATUS_SUCCESS );
+    else
+        req->pending = 1;
 
     for (i = 0; i < req->count; ++i)
         sock_reselect( req->sockets[i].sock );




More information about the wine-cvs mailing list