Repository navigation
fix(vm_service): reconnect when the connection to the VM service drops - #566
Open
Catherine1401 wants to merge 1 commit into
Open
Catherine1401 wants to merge 1 commit into
Catherine1401 wants to merge 1 commit into
Conversation
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.
Problem
flutter-tools.vm_serviceis the client behind the widget inspector navigation (it listens to theDebugstream and reacts toInspectevents). Once its WebSocket drops (the server closes it, anadb forwardhiccup, ...) the client callsdisconnect(), which also forgets every registered stream handler, and never reconnects. From then on selecting a widget in the inspector silently does nothing until the app is restarted.The hand-rolled WebSocket handling also loses data:
HTTP/1.1 101response are discarded, so a first event sent right after the handshake is lost;Changes
vm_service.luanow sits on top offlutter-tools.utils.websocket(already used by the DTD client), which buffers the handshake, keeps the bytes after it, assembles fragmented messages and answers ping/close frames.stream_listen. It notifies when the connection is lost and when it is back, and callson_errorafter giving up.on_errorimmediately and is not retried, as before.disconnect()cancels any pending reconnect, and a generation counter makes callbacks of an old socket no-ops.debugger_runnernow always callsvm_service.disconnect()when the debug session ends, so a pending reconnect does not outlive the session.tests/vm_service_spec.lua(7 tests) runs the client against an in-process WebSocket server.Verification
tests/vm_service_spec.lua: 7/7 pass with this change. Against currentmainthree of them fail: the event sent together with the handshake response, the fragmented message, and the reconnect.dart:developerinspect()every second, and a TCP proxy between the client and the VM that is cut after the first events.main: 3Inspectevents, thenis_connected()staysfalseand no further event arrives.Debugagain and receives 3 moreInspectevents.main(ui_specprogress resend, 2 tests, anddebugger_runner_spec"reports adapter progress", 1 test).stylua --check .is clean.Notes
While testing I noticed that
vm_service.request(method, {})serializes empty params as[], which makes the Dart VM service isolate throw (type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>') and stop. No current caller does this, so I left it out of this change.🤖 Generated with Claude Code