From 835ce042958f3b51df4ad5b554bea1c027613520 Mon Sep 17 00:00:00 2001 From: Vladimir Dubrovin <3proxy@3proxy.ru> Date: Sat, 24 Oct 2026 22:17:19 +0300 Subject: [PATCH] Event loop on Windows: woken over a loopback TCP connection WSAPoll() never reported the UDP socket which sent to itself to wake the loop: a message from another thread waited for the timeout, and loopstop() did not end looprun(). The loop is woken over a TCP connection on the loopback instead, as its sockets are reported. Co-Authored-By: Claude Opus 5.5 --- src/loop.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/loop.c b/src/loop.c index 63f3cdf..559d17c 100644 --- a/src/loop.c +++ b/src/loop.c @@ -56,22 +56,31 @@ static int wakeinit(struct loop *l){ if(fd < 0) return 1; l->wakerd = l->wakewr = fd; #elif defined _WIN32 - /* no pipe to poll: a UDP socket sending to itself */ + /* no pipe to poll: a TCP connection over the loopback, which WSAPoll() + reports as it does not a UDP socket sending to itself */ struct sockaddr_in sa; - int len = sizeof(sa); - SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + int len = sizeof(sa), one = 1; + SOCKET ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP), a = INVALID_SOCKET, b = INVALID_SOCKET; - if(s == INVALID_SOCKET) return 1; + if(ls == INVALID_SOCKET) return 1; memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - if(bind(s, (struct sockaddr *)&sa, sizeof(sa)) || getsockname(s, (struct sockaddr *)&sa, &len) || - connect(s, (struct sockaddr *)&sa, sizeof(sa))){ - closesocket(s); + if(bind(ls, (struct sockaddr *)&sa, sizeof(sa)) || listen(ls, 1) || + getsockname(ls, (struct sockaddr *)&sa, &len) || + (a = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET || + connect(a, (struct sockaddr *)&sa, sizeof(sa)) || + (b = accept(ls, NULL, NULL)) == INVALID_SOCKET){ + if(a != INVALID_SOCKET) closesocket(a); + closesocket(ls); return 1; } - setnonblock(s); - l->wakerd = l->wakewr = s; + closesocket(ls); + setsockopt(a, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)); + setnonblock(a); + setnonblock(b); + l->wakewr = a; + l->wakerd = b; #else int p[2]; @@ -89,6 +98,7 @@ static int wakeinit(struct loop *l){ static void wakefree(struct loop *l){ #ifdef _WIN32 closesocket(l->wakerd); + closesocket(l->wakewr); #else close(l->wakerd); if(l->wakewr != l->wakerd) close(l->wakewr);