]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
slirp: check TCP connect completion with SO_ERROR
authorStefan Reinauer <stefan.reinauer@coreboot.org>
Thu, 28 May 2026 00:38:28 +0000 (17:38 -0700)
committerStefan Reinauer <stefan.reinauer@coreboot.org>
Tue, 2 Jun 2026 22:33:30 +0000 (15:33 -0700)
The nonblocking connect path treated a writable socket as connected
and then used a zero-length send as the failure probe. That is not a
reliable completion check and can mis-handle failed or pending guest
TCP connects.

Use getsockopt(SO_ERROR) when select reports the socket writable. Keep
pending connects pending, and only clear SS_ISFCONNECTING after the
host socket has no pending error.

slirp/slirp.cpp

index d8e5b23f0a41971ab6fa4c64f97d095150683ec2..0df263cd80d33604e63aed7c1dee08abf629737b 100644 (file)
@@ -450,21 +450,20 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
                                 * Check for non-blocking, still-connecting sockets
                                 */
                                if (so->so_state & SS_ISFCONNECTING) {
-                                       /* Connected */
-                                       so->so_state &= ~SS_ISFCONNECTING;
-
-                                       ret = send(so->s, (const char*)&ret, 0, 0);
-                                       if (ret < 0) {
-                                               /* XXXXX Must fix, zero bytes is a NOP */
-                                               int error = WSAGetLastError();
-                                               if (error == EAGAIN || error == WSAEWOULDBLOCK  ||
-                                                       error == WSAEINPROGRESS  || error == WSAENOTCONN)
+                                       int error = 0;
+                                       socklen_t error_len = sizeof(error);
+                                       if (getsockopt(so->s, SOL_SOCKET, SO_ERROR,
+                                               (char*)&error, &error_len) < 0)
+                                               error = WSAGetLastError();
+                                       if (error) {
+                                               if (error == EAGAIN || error == WSAEWOULDBLOCK ||
+                                                       error == WSAEINPROGRESS || error == WSAENOTCONN)
                                                        continue;
-                             
                                                /* else failed */
                                                so->so_state = SS_NOFDREF;
+                                       } else {
+                                               so->so_state &= ~SS_ISFCONNECTING;
                                        }
-                                       /* else so->so_state &= ~SS_ISFCONNECTING; */
 
                                        /*
                                         * Continue tcp_input