Fix a teardown race in HttpProxyStateTracker - #41097
Merged
Ben Hillis (benhillis) merged 2 commits intoJul 24, 2026
Merged
Conversation
HttpProxyStateTracker::QueryProxySettingsAsync() published the WinHTTP resolver/session handles and reset m_requestFinished only after calling WinHttpGetProxySettingsEx(). Since that call can complete (or fail synchronously) before returning, the destructor could run concurrently with request setup: it could observe m_requestFinished still signaled and tear down the queue and unregister the proxy-change notification while a request was still starting up, or close handles before they were fully published. Fix this by: - Adding a lock (m_requestLock) that serializes handle creation/teardown between QueryProxySettingsAsync, RequestCompleted, and the destructor, plus an m_stopping flag so no new request can start once teardown has begun. - Marking the request as in-flight (resetting m_requestFinished and setting m_queryState) before calling WinHttpGetProxySettingsEx, so the destructor cannot proceed past m_requestFinished.wait() while a request is actually outstanding. - Setting WINHTTP_OPTION_CONTEXT_VALUE on the resolver handle so that WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING always carries a valid context, including when WinHttpGetProxySettingsEx fails synchronously (which produces no completion callback), so RequestClosed() reliably runs and re-signals m_requestFinished instead of leaving it stuck. - Reordering the constructor to register the proxy-change notification before submitting the initial query, so a throw during registration can't leave a queued task running against a partially-constructed object. Tested locally with repeated concurrent wsl -e / wsl --shutdown races (including tight construct-then-shutdown loops) with no crashes or hangs observed.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes a teardown/startup race in HttpProxyStateTracker (WSL service) around WinHTTP async proxy queries, ensuring the tracker canât begin a new query while teardown is in progress and that request lifetime is reliably tracked even when WinHTTP completes (or fails) synchronously.
Changes:
- Added a request lifecycle lock (
m_requestLock) plusm_stoppingto serialize request startup/teardown and prevent new requests during destruction. - Marked requests as in-flight before calling
WinHttpGetProxySettingsExto prevent teardown from observing a âfinishedâ state while a request is actually starting. - Set
WINHTTP_OPTION_CONTEXT_VALUEon the resolver handle soWINHTTP_CALLBACK_STATUS_HANDLE_CLOSINGalways has a valid context, enablingRequestClosed()to reliably re-signalm_requestFinished. - Reordered constructor operations to register proxy-change notifications before submitting the initial query task.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/windows/service/exe/LxssHttpProxy.h | Introduces request lifecycle synchronization members (m_requestLock, m_stopping) and guards WinHTTP handles with the new lock. |
| src/windows/service/exe/LxssHttpProxy.cpp | Applies the new synchronization to query start/completion/destruction, sets resolver context via WINHTTP_OPTION_CONTEXT_VALUE, and reorders initialization to avoid partially-constructed usage. |
Blue (OneBlue)
approved these changes
Jul 23, 2026
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.
Fix a teardown race in
HttpProxyStateTrackerHttpProxyStateTracker::QueryProxySettingsAsync()published the WinHTTP resolver/session handles and resetm_requestFinishedonly after callingWinHttpGetProxySettingsEx(). Since that call can complete (or fail synchronously) before it even returns, the destructor could run concurrently with request setup: it could observem_requestFinishedstill signaled and tear down the message queue / unregister the proxy-change notification while a request was still starting up, or tear down handles before they were fully published.This PR fixes that by:
m_requestLock) that serializes handle creation/teardown betweenQueryProxySettingsAsync,RequestCompleted, and the destructor, plus anm_stoppingflag so no new request can start once teardown has begun.m_requestFinishedand settingm_queryState) before callingWinHttpGetProxySettingsEx, so the destructor can't proceed pastm_requestFinished.wait()while a request is actually outstanding.WINHTTP_OPTION_CONTEXT_VALUEon the resolver handle so thatWINHTTP_CALLBACK_STATUS_HANDLE_CLOSINGalways carries a valid context â including whenWinHttpGetProxySettingsExfails synchronously (which produces no completion callback) â soRequestClosed()reliably runs and re-signalsm_requestFinishedinstead of leaving it stuck.Testing
wsl -e/wsl --shutdownraces (including tight construct-then-shutdown loops) with no crashes or hangs observed, and the service PID remained stable throughout.