Skip to content

Defer WinHTTP HTTP/2 loopback connection closure until server disposal - #134181

Merged
rzikm merged 1 commit into
dotnet:mainfrom
rzikm:rzikm/winhttp-cookie-test-synchronization
Sep 18, 2026
Merged

rzikm merged 1 commit into
dotnet:mainfrom
rzikm:rzikm/winhttp-cookie-test-synchronization

Conversation

@rzikm

@rzikm rzikm commented Sep 18, 2026

Copy link
Copy Markdown
Member

WinHTTP can discard buffered response data when the loopback server sends FIN before the client consumes it, causing error 12030. This affects more than cookie tests: the same failure signature also appeared in ClientCertificateTest.UseClientCertOnHttp2_OSSupportsIt_Success. Synchronizing individual tests leaves other paths exposed.

This change moves lifetime management into the shared HTTP/2 loopback infrastructure. In WinHTTP tests, connection disposal sends GOAWAY but retains the transport until the enclosing server is disposed, normally after both client and server callbacks complete. Retired connections do not prevent subsequent connections from being accepted. Automatic GOAWAY respects earlier last-stream boundaries, and cleanup tolerates the server closing a connection during asynchronous disposal.

The behavior is enabled by default only for WinHTTP tests. Explicit shutdown methods remain immediate, and tests requiring the original disposal behavior can set DeferConnectionClose = false. The HTTP/2 cookie tests quarantined under #126867 are re-enabled; no cookie-specific synchronization or product code changes are needed.

Validation

  • WinHTTP functional suites: 1,749 tests on .NET 11 and 667 on .NET Framework, with zero failures and 41/28 existing skips respectively.
  • WinHTTP unit tests: 173 passed.
  • SocketsHttpHandler HTTP/2 protocol and cookie tests: 212 passed.
  • Ten repetitions of the affected cookie, certificate, and lifetime tests: 800 passes, no failures or skips.
  • Regression tests verify that responses remain readable after connection disposal and that physical closure during deferred disposal completes safely. Both regressions were checked against the corresponding unfixed behavior. These verify the lifetime contract, not a deterministic reproduction of native error 12030.

Fixes #133779
Fixes #130458
Fixes #126867

... and countless others that boil down to "Error 12030 calling WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, 'The connection with the server was terminated abnormally'."

Note

This pull request description and changes were generated with GitHub Copilot.

Keep retired connections open until the enclosing loopback server is disposed so WinHTTP can consume buffered responses before receiving FIN. Preserve explicit shutdown behavior, cover deferred disposal and teardown races, and re-enable HTTP/2 cookie tests.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings September 18, 2026 10:50
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 4 pipeline(s).
12 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @karelz, @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

@rzikm
rzikm requested a review from a team September 18, 2026 11:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Two moderate concurrency and cleanup-safety issues remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

This PR defers WinHTTP HTTP/2 loopback connection closure until server disposal, preserving buffered responses and re-enabling affected cookie tests.

Changes:

  • Adds deferred disposal, GOAWAY tracking, and cleanup regression tests.
  • Re-enables WinHTTP HTTP/2 cookie tests.
  • Updates shared loopback connection lifecycle handling.
File summaries
File Summary
src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/WinHttpHandlerTest.cs Adds deferred-disposal regression tests.
src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/PlatformHandlerTest.cs Re-enables HTTP/2 cookie tests.
src/libraries/Common/tests/System/Net/Http/Http2LoopbackServer.cs Manages retained connections and server cleanup. Moderate finding (1 vote): deferred-close state visibility is unsynchronized.
src/libraries/Common/tests/System/Net/Http/Http2LoopbackConnection.cs Implements deferred GOAWAY and closure behavior. Moderate finding (2 votes): concurrent field cleanup can race active I/O and cause NullReferenceException.
Review details

Suppressed comments (1)

src/libraries/Common/tests/System/Net/Http/Http2LoopbackServer.cs:94

  • IsCloseDeferred is read under the server's _connections lock, but _closeDeferred is written by Http2LoopbackConnection.DisposeAsync without that lock and is a plain bool. The lock therefore does not establish visibility between a completed deferred disposal and a concurrent EstablishConnectionAsync, so the new-connection path can still observe false and throw Connection already established. Synchronize this state transition (for example with matching Volatile.Read/Volatile.Write, or by using the server lock for both sides).
                if (!AllowMultipleConnections && _connections.Exists(c => !c.IsCloseDeferred))
  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Lite

@rzikm

rzikm commented Sep 18, 2026

Copy link
Copy Markdown
Member Author

/ba-g only known errors

@rzikm
rzikm enabled auto-merge (squash) September 18, 2026 15:51
@rzikm
rzikm merged commit b876d4e into dotnet:main Sep 18, 2026
84 of 86 checks passed
@rzikm

rzikm commented Sep 18, 2026

Copy link
Copy Markdown
Member Author

/backport to release/11.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0 (link to workflow run)

@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 12.0-preview1 milestone Sep 19, 2026
mrek-msft pushed a commit that referenced this pull request Sep 21, 2026
… server disposal (#134204)

Backport of #134181 to release/11.0

/cc @rzikm

## Customer Impact

Test-only change to reduce CI noise

Co-authored-by: Radek Zikmund <32671551+rzikm@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

3 participants