[PATCH 2/3] server: Don't reset socket error in poll_socket.

Piotr Caban wine at gitlab.winehq.org
Fri Jun 10 11:01:02 CDT 2022


From: Piotr Caban <piotr at codeweavers.com>

Otherwise socket error may be cleared in poll_socket causing ioctl SO_ERROR calls to return no error.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51433
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
---
 server/sock.c | 34 ++++++++++++++++++++++++++--------
 1 file changed, 26 insertions(+), 8 deletions(-)

diff --git a/server/sock.c b/server/sock.c
index 8a0f3198c4e..c4bbd388097 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -631,13 +631,28 @@ static void sock_wake_up( struct sock *sock )
     }
 }
 
-static inline int sock_error( struct fd *fd )
+static inline int sock_error( struct sock *sock, int *error )
 {
-    unsigned int optval = 0;
-    socklen_t optlen = sizeof(optval);
+    socklen_t len = sizeof(*error);
 
-    getsockopt( get_unix_fd(fd), SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
-    return optval;
+    if (getsockopt( get_unix_fd(sock->fd), SOL_SOCKET, SO_ERROR, (void *)error, &len) < 0)
+        return -1;
+
+    if (sock->state == SOCK_CONNECTING)
+    {
+        if (*error)
+            sock->errors[AFD_POLL_BIT_CONNECT_ERR] = *error;
+        else
+            *error = sock->errors[AFD_POLL_BIT_CONNECT_ERR];
+    }
+    else if (sock->state == SOCK_LISTENING)
+    {
+        if (*error)
+            sock->errors[AFD_POLL_BIT_ACCEPT] = *error;
+        else
+            *error = sock->errors[AFD_POLL_BIT_CONNECT_ERR];
+    }
+    return 0;
 }
 
 static void free_accept_req( void *private )
@@ -1120,9 +1135,9 @@ static void sock_poll_event( struct fd *fd, int event )
     case SOCK_CONNECTING:
         if (event & (POLLERR|POLLHUP))
         {
+            sock_error( sock, &error );
             sock->state = SOCK_UNCONNECTED;
             event &= ~POLLOUT;
-            error = sock_error( fd );
         }
         else if (event & POLLOUT)
         {
@@ -1133,7 +1148,7 @@ static void sock_poll_event( struct fd *fd, int event )
 
     case SOCK_LISTENING:
         if (event & (POLLERR|POLLHUP))
-            error = sock_error( fd );
+            sock_error( sock, &error );
         break;
 
     case SOCK_CONNECTED:
@@ -3123,9 +3138,12 @@ static void poll_socket( struct sock *poll_sock, struct async *async, int exclus
 
         if (flags)
         {
+            int error = 0;
+
             signaled = TRUE;
             req->sockets[i].flags = flags;
-            req->sockets[i].status = sock_get_ntstatus( sock_error( sock->fd ) );
+            sock_error( sock, &error );
+            req->sockets[i].status = sock_get_ntstatus( error );
         }
 
         /* FIXME: do other error conditions deserve a similar treatment? */
-- 
GitLab


https://gitlab.winehq.org/wine/wine/-/merge_requests/225



More information about the wine-devel mailing list