mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-28 22:05:48 +08:00
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 <noreply@anthropic.com>
This commit is contained in:
parent
30f6043160
commit
835ce04295
28
src/loop.c
28
src/loop.c
@ -56,22 +56,31 @@ static int wakeinit(struct loop *l){
|
|||||||
if(fd < 0) return 1;
|
if(fd < 0) return 1;
|
||||||
l->wakerd = l->wakewr = fd;
|
l->wakerd = l->wakewr = fd;
|
||||||
#elif defined _WIN32
|
#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;
|
struct sockaddr_in sa;
|
||||||
int len = sizeof(sa);
|
int len = sizeof(sa), one = 1;
|
||||||
SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
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));
|
memset(&sa, 0, sizeof(sa));
|
||||||
sa.sin_family = AF_INET;
|
sa.sin_family = AF_INET;
|
||||||
sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||||
if(bind(s, (struct sockaddr *)&sa, sizeof(sa)) || getsockname(s, (struct sockaddr *)&sa, &len) ||
|
if(bind(ls, (struct sockaddr *)&sa, sizeof(sa)) || listen(ls, 1) ||
|
||||||
connect(s, (struct sockaddr *)&sa, sizeof(sa))){
|
getsockname(ls, (struct sockaddr *)&sa, &len) ||
|
||||||
closesocket(s);
|
(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;
|
return 1;
|
||||||
}
|
}
|
||||||
setnonblock(s);
|
closesocket(ls);
|
||||||
l->wakerd = l->wakewr = s;
|
setsockopt(a, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one));
|
||||||
|
setnonblock(a);
|
||||||
|
setnonblock(b);
|
||||||
|
l->wakewr = a;
|
||||||
|
l->wakerd = b;
|
||||||
#else
|
#else
|
||||||
int p[2];
|
int p[2];
|
||||||
|
|
||||||
@ -89,6 +98,7 @@ static int wakeinit(struct loop *l){
|
|||||||
static void wakefree(struct loop *l){
|
static void wakefree(struct loop *l){
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
closesocket(l->wakerd);
|
closesocket(l->wakerd);
|
||||||
|
closesocket(l->wakewr);
|
||||||
#else
|
#else
|
||||||
close(l->wakerd);
|
close(l->wakerd);
|
||||||
if(l->wakewr != l->wakerd) close(l->wakewr);
|
if(l->wakewr != l->wakerd) close(l->wakewr);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user