[dotnet-watch] Fix WebSocket transport crash on Ctrl+R restart#53648
Merged
jonathanpeppers merged 2 commits intorelease/10.0.3xxfrom Apr 1, 2026
Merged
[dotnet-watch] Fix WebSocket transport crash on Ctrl+R restart#53648jonathanpeppers merged 2 commits intorelease/10.0.3xxfrom
jonathanpeppers merged 2 commits intorelease/10.0.3xxfrom
Conversation
Fixes #53634 When restarting a mobile/WebSocket app via Ctrl+R, the child process is killed which closes the TCP connection. Kestrel tears down the HTTP context, and then RunningProject.DisposeAsync tries to dispose the WebSocket — hitting an ObjectDisposedException on the already-disposed IFeatureCollection. The ListenForResponsesAsync loop also logs a spurious WebSocketException error. Fixes: - RequestHandler.Dispose: catch ObjectDisposedException when the underlying Kestrel HTTP context is already torn down - IsExpectedConnectionTermination: treat WebSocketException as expected when the socket state is Aborted (remote disconnected) Tests: - CtrlC_ShutsDownCleanly: verifies clean shutdown with WebSocket transport (already worked, added for coverage) - CtrlR_RestartsCleanly: verifies restart without WebSocketException or ObjectDisposedException errors (was broken, now passes) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes a dotnet-watch shutdown/restart crash path specific to WebSocket-based hot reload transports (mobile scenarios), where killing the child process can tear down Kestrel’s HTTP context before the WebSocket transport is disposed.
Changes:
- Treat
ObjectDisposedExceptionduring WebSocket transport disposal/reads as expected in relevant scenarios. - Treat
WebSocketExceptionas expected when the client socket is inAbortedstate to avoid spurious error logs. - Add dotnet-watch tests covering Ctrl+C shutdown and Ctrl+R restart with WebSocket transport.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| test/dotnet-watch.Tests/HotReload/MobileHotReloadTests.cs | Adds Ctrl+C/Ctrl+R regression tests for WebSocket hot reload transport. |
| src/Dotnet.Watch/HotReloadClient/WebSocketClientTransport.cs | Makes WebSocket transport shutdown/restart more resilient by handling expected disposal/abort exceptions. |
tmat
reviewed
Mar 31, 2026
tmat
reviewed
Mar 31, 2026
- ClearOutput before SendControlC/SendControlR to avoid matching stale output - Assert exit code 0 specifically in Ctrl+C test - Use WaitForOutputLineContaining for post-restart Started assertion Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
tmat
approved these changes
Apr 1, 2026
This was referenced Apr 1, 2026
Open
54 tasks
jonathanpeppers
added a commit
that referenced
this pull request
Apr 27, 2026
Fixes: #53634 When a mobile/WebSocket app is shut down (Ctrl+C) or restarted (Ctrl+R), the child process is killed which closes the TCP connection. Kestrel tears down the HTTP context, and then `RunningProject.DisposeAsync` tries to dispose the WebSocket — hitting an `ObjectDisposedException` on the already-disposed `IFeatureCollection`. The `ListenForResponsesAsync` loop also logs a spurious `WebSocketException` error. **Fixes:** - `RequestHandler.Dispose`: catch `ObjectDisposedException` when the underlying Kestrel HTTP context is already torn down - `IsExpectedConnectionTermination`: treat `WebSocketException` as expected when the socket state is `Aborted` (remote disconnected) **Tests:** - `CtrlC_ShutsDownCleanly`: verifies clean shutdown with WebSocket transport - `CtrlR_RestartsCleanly`: verifies restart without `WebSocketException` or `ObjectDisposedException` errors Both tests fail without the fix. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
22 tasks
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.
Fixes #53634
When a mobile/WebSocket app is shut down (Ctrl+C) or restarted (Ctrl+R), the child process is killed which closes the TCP connection. Kestrel tears down the HTTP context, and then
RunningProject.DisposeAsynctries to dispose the WebSocket — hitting anObjectDisposedExceptionon the already-disposedIFeatureCollection. TheListenForResponsesAsyncloop also logs a spuriousWebSocketExceptionerror.Fixes:
RequestHandler.Dispose: catchObjectDisposedExceptionwhen the underlying Kestrel HTTP context is already torn downIsExpectedConnectionTermination: treatWebSocketExceptionas expected when the socket state isAborted(remote disconnected)Tests:
CtrlC_ShutsDownCleanly: verifies clean shutdown with WebSocket transportCtrlR_RestartsCleanly: verifies restart withoutWebSocketExceptionorObjectDisposedExceptionerrorsBoth tests fail without the fix.