From 991c2d765dc003e43b8814dc191b9e81140df4cd Mon Sep 17 00:00:00 2001 From: Kartik Naik Date: Tue, 14 Jul 2026 14:18:48 +0530 Subject: honor the requested timeout in the win32 poll shim --- apps/openssl/compat/poll_win.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/openssl/compat/poll_win.c b/apps/openssl/compat/poll_win.c index 30f6b60..c518962 100644 --- a/apps/openssl/compat/poll_win.c +++ b/apps/openssl/compat/poll_win.c @@ -249,8 +249,6 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms) wait_rc = WAIT_FAILED; looptime_ms = (timeout_ms > 100 || timeout_ms == -1) ? 100 : timeout_ms; - if (timeout_ms == -1) - timeout_ms = INFINITE; do { TIMEVAL tv; @@ -280,7 +278,7 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms) /* * If we signaled on a file handle, don't wait on the sockets. */ - if (wait_rc >= WAIT_OBJECT_0 && + if (num_handles && wait_rc >= WAIT_OBJECT_0 && (wait_rc <= WAIT_OBJECT_0 + num_handles - 1)) { tv.tv_usec = 0; handle_signaled = 1; @@ -298,7 +296,7 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms) timespent_ms += looptime_ms; - } while (timespent_ms < timeout_ms); + } while (timeout_ms == -1 || timespent_ms < timeout_ms); rc = 0; num_handles = 0; -- cgit v1.2.3-55-g6feb From b901cbc4d84bd4eb5dbb27dabc329ba03457274a Mon Sep 17 00:00:00 2001 From: Kartik Naik Date: Wed, 15 Jul 2026 15:48:00 +0530 Subject: poll_win: restore fd_sets before each select() retry select() strips not-ready descriptors from the fd_sets, so a timed-out pass leaves them empty and the next pass calls select() with three empty sets, which Windows rejects with WSAEINVAL. Keep a pristine copy and restore it before each retry so an idle socket waits out the timeout. --- apps/openssl/compat/poll_win.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/apps/openssl/compat/poll_win.c b/apps/openssl/compat/poll_win.c index c518962..0d15522 100644 --- a/apps/openssl/compat/poll_win.c +++ b/apps/openssl/compat/poll_win.c @@ -166,6 +166,7 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms) * select machinery */ fd_set rfds, wfds, efds; + fd_set rfds_in, wfds_in, efds_in; int rc; int num_sockets; @@ -250,12 +251,27 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms) looptime_ms = (timeout_ms > 100 || timeout_ms == -1) ? 100 : timeout_ms; + /* + * select() clears every descriptor that is not ready from the + * fd_sets, so a pass that times out leaves them empty. Keep a + * pristine copy and restore it before each select(), otherwise the + * next pass hands select() three empty sets and Windows fails it with + * WSAEINVAL instead of waiting out the remaining timeout. + */ + rfds_in = rfds; + wfds_in = wfds; + efds_in = efds; + do { TIMEVAL tv; tv.tv_sec = 0; tv.tv_usec = looptime_ms * 1000; int handle_signaled = 0; + rfds = rfds_in; + wfds = wfds_in; + efds = efds_in; + /* * Check if any file handles have signaled */ -- cgit v1.2.3-55-g6feb From 9082d30d64e6765f930dc320addd1fda134a78c1 Mon Sep 17 00:00:00 2001 From: Kartik Naik Date: Thu, 16 Jul 2026 11:52:45 +0530 Subject: poll_win: cap the final wait pass at the remaining time The wait loop always sleeps in fixed 100ms slices, so a 250ms timeout runs three full passes and takes ~300ms. Clamp each pass to the time remaining so the total wait matches the requested timeout. --- apps/openssl/compat/poll_win.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/openssl/compat/poll_win.c b/apps/openssl/compat/poll_win.c index 0d15522..8e28349 100644 --- a/apps/openssl/compat/poll_win.c +++ b/apps/openssl/compat/poll_win.c @@ -264,6 +264,14 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms) do { TIMEVAL tv; + + /* + * Cap the wait at the time remaining so the final pass + * does not overshoot the requested timeout. + */ + if (timeout_ms != -1 && timeout_ms - timespent_ms < looptime_ms) + looptime_ms = timeout_ms - timespent_ms; + tv.tv_sec = 0; tv.tv_usec = looptime_ms * 1000; int handle_signaled = 0; -- cgit v1.2.3-55-g6feb