From 41edaa9757773599d269b4bf38703ecb0b6c7e41 Mon Sep 17 00:00:00 2001 From: Vladimir Dubrovin <3proxy@3proxy.ru> Date: Tue, 13 Oct 2026 13:09:41 +0300 Subject: [PATCH] Leave a hung-up socket out of poll() rather than pass an invalid one A socket which hung up and of which nothing is asked was given to poll() as INVALID_SOCKET, so that poll() would not return at once for the hang-up every time. poll() ignores a negative descriptor, but SOCKET is unsigned on Windows, and WSAPoll fails the whole call for it: sockmap() ended the session as soon as a client half-closed. Such a socket is now not in the array at all. Co-Authored-By: Claude Opus 5.5 (cherry picked from commit 98fd0f329f16e1404cb34ce1f8b25ebd27875836) --- src/sockmap.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/sockmap.c b/src/sockmap.c index 32d51be..223ca42 100644 --- a/src/sockmap.c +++ b/src/sockmap.c @@ -99,6 +99,8 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){ int CLIENTTERMREAD = 0, CLIENTTERMWRITE = 0, SERVERTERMREAD = 0, SERVERTERMWRITE = 0; /* the side has hung up: closed by the peer after its own was shut down */ int CLIENTHUP = 0, SERVERHUP = 0; + /* whether the side's socket is in this round's poll() */ + int clipolled = 1, srvpolled = 1; int after = 0; struct pollfd fds[8]; int fdsc = 0; @@ -665,8 +667,10 @@ log("done read from server to buf"); )) cli_events |= POLLOUT; /* poll() reports a hang-up whatever is asked, and would - return at once every time: wait for the other side then */ - if(!cli_events && CLIENTHUP) fds[fdsc].fd = INVALID_SOCKET; + return at once every time: the socket is left out then, + rather than given as an invalid one, which WSAPoll takes + for an error */ + clipolled = cli_events || !CLIENTHUP; if(cli_events){ fds[fdsc].fd = param->clisock; fds[fdsc].events = cli_events; @@ -678,6 +682,8 @@ log("wait writing to client"); #endif } } + else if(!clipolled){ + } else if(cli_events){ if(fds[fdsc].revents & (POLLERR|POLLNVAL)) { CLIENTTERMREAD = 1; @@ -713,7 +719,7 @@ log("ready to write to client"); read, once the buffer has room for it */ CLIENTHUP = 1; } - fdsc++; + if(clipolled) fdsc++; // if(!SERVERTERMREAD || !SERVERTERMWRITE){ if(!after){ @@ -727,7 +733,7 @@ log("ready to write to client"); #endif )) srv_events |= POLLOUT; - if(!srv_events && SERVERHUP) fds[fdsc].fd = INVALID_SOCKET; + srvpolled = srv_events || !SERVERHUP; if(srv_events){ fds[fdsc].fd = param->remsock; fds[fdsc].events = srv_events; @@ -739,6 +745,8 @@ log("wait writing from server"); #endif } } + else if(!srvpolled){ + } else if(srv_events){ if(fds[fdsc].revents & (POLLERR|POLLNVAL)) { #ifdef WITHLOG @@ -780,7 +788,7 @@ log("server terminated connection"); /* the rest of the answer may still be waiting to be read */ SERVERHUP = 1; } - fdsc++; + if(srvpolled) fdsc++; // } #ifdef WITHSPLICE {