Repository navigation
Let ClientImpl::stop() interrupt a request waiting on Windows - #2653
Merged
Merged
Conversation
stop() shuts the socket down to end a request in flight, but on Windows that does not wake a read waiting in WSAPoll (yhirose#1396). The request then waited until the server answered, the read timeout passed, or the OS dropped the connection. stop() now also sets a flag, and send_() gives the request's stream an interrupt check that reads it, as SSEClient::stop() does since 801bf2e. The wait for data then ends within 100 ms on every platform. A request started after stop() clears the flag. A redirect or a digest retry sent inside the request keeps it. select_read_interruptible() now rounds its last wait up to a whole millisecond. poll() takes milliseconds, and the wait ended up to 1 ms before the deadline, which MaxTimeoutTest caught once every client request waited through this function.
Owner
|
@yosh-matsuda thanks for the thorough investigation and fix! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related to #1396. That issue is closed, but a comment of 2026-09-01 reports that
Client::stop()still does not end a request on Windows with the latest version.Problem
stop()ends a request in flight withshutdown()on its socket. On Linux and macOS this wakes thepoll()that waits for the response. On Windows,shutdown()does not wake aWSAPoll()on the same socket. The request then waits until the server answers, the read timeout passes (300 s by default), or the OS drops the connection.801bf2e fixed the same problem for
SSEClient::stop(). This PR uses the same mechanism forClientImpl::stop().Change
stop()also sets the atomic flagstop_requested_when a request is in flight.send_()gives the stream of the request an interrupt check that reads the flag, withset_read_interrupt()from 801bf2e. A wait for data then ends within 100 ms on every platform.shutdown_socket()stays, so Linux and macOS still wake at once.select_read_interruptible()now rounds its last wait up to a whole millisecond.poll()takes whole milliseconds, and the old code dropped the rest, so the wait could end up to 1 ms before the deadline. The SSE path had the same error. When every client request waits through this function,MaxTimeoutTest.ContentStreamandMaxTimeoutTest.ContentStreamSSLfail with "Timeout exceeded by -1ms" on the Mbed TLS, wolfSSL, and BoringSSL jobs.stop()sets the flag undersocket_mutex_, andsend_()counts the request as in flight under the same lock. Thus astop()that comes after that point, but before the request starts to wait, is not lost. Astop()before that point closes the idle socket, as before.Notes:
SSEClientuses the same slice.ClientImplgets one new member, so abidiff reports an ABI change against v0.64.0.Test
ClientStopTest.StopEndsWaitForResponsesends a request to a handler that does not answer. Another thread callsstop()once, and the test expects the request to end withError::Readwithin 2 s.MaxTimeoutTest.shutdown_socket()removed fromstop()to imitate Windows, the test fails without the fix and passes in approximately 0.2 s with the fix.