From: Piotr Caban piotr@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@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? */