From 01a6350106d57b4b39be791db811b958c415c0fe Mon Sep 17 00:00:00 2001 From: Stefan Reinauer Date: Wed, 27 May 2026 17:38:28 -0700 Subject: [PATCH] slirp: check TCP connect completion with SO_ERROR 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 | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/slirp/slirp.cpp b/slirp/slirp.cpp index d8e5b23f..0df263cd 100644 --- a/slirp/slirp.cpp +++ b/slirp/slirp.cpp @@ -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 -- 2.47.3