Skip to content

Commit e891cac

Browse files
DanTupCommit Queue
authored andcommitted
[dds/dap] Handle some additional kinds of errors when the VM Service connection shuts down
This handles an RPC Error -32000 with text "Service connection disposed" as reported in #60851. It extracts some of this logic into an extension on RPCError to simplify checking in multiple places. Unfortunately I can't reproduce the specific conditions that produce this error in a test (it probably requires terminated the VM Service at just the right time during startup or an isolate starting?). Fixes #60851 Change-Id: Iae945f60290766164d04b91d851fbb8b58f178c6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/432944 Reviewed-by: Derek Xu <[email protected]> Commit-Queue: Ben Konyi <[email protected]> Reviewed-by: Ben Konyi <[email protected]>
1 parent bf9aced commit e891cac

File tree

5 files changed

+34
-13
lines changed

5 files changed

+34
-13
lines changed

pkg/dds/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# 5.0.3
2+
- [DAP] Handle some additional errors if the VM Service is shutting down during an attempt to resume an isolate.
23
- [DAP] Stack frames with dots in paths will now be parsed and have locations attached to `OutputEvents`s.
34
- [DAP] Responses to `evaluateRequest` that are lists now include `indexedVariables` to allow for client-side paging.
45

pkg/dds/lib/src/dap/adapters/dart.dart

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import 'package:path/path.dart' as path;
1515
import 'package:vm_service/vm_service.dart' as vm;
1616

1717
import '../../../dds.dart';
18-
import '../../rpc_error_codes.dart';
1918
import '../base_debug_adapter.dart';
2019
import '../isolate_manager.dart';
2120
import '../logging.dart';
@@ -2838,8 +2837,7 @@ abstract class DartDebugAdapter<TL extends LaunchRequestArguments,
28382837
// outside of the DAP (eg. closing the simulator) so it's possible our
28392838
// requests will fail in this way before we've handled any event to set
28402839
// `isTerminating`.
2841-
if (e.code == RpcErrorCodes.kServiceDisappeared ||
2842-
e.code == RpcErrorCodes.kConnectionDisposed) {
2840+
if (e.isServiceDisposedError) {
28432841
return null;
28442842
}
28452843

@@ -2853,15 +2851,6 @@ abstract class DartDebugAdapter<TL extends LaunchRequestArguments,
28532851
if (isTerminating) {
28542852
return null;
28552853
}
2856-
2857-
// Always ignore "client is closed" and "closed with pending request"
2858-
// errors because these can always occur during shutdown if we were
2859-
// just starting to send (or had just sent) a request.
2860-
if (e.message.contains("The client is closed") ||
2861-
e.message.contains("The client closed with pending request") ||
2862-
e.message.contains("Service connection disposed")) {
2863-
return null;
2864-
}
28652854
}
28662855

28672856
// Otherwise, it's an unexpected/unknown failure and should be rethrown.

pkg/dds/lib/src/dap/isolate_manager.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,9 @@ class IsolateManager {
378378
if (e.code == RpcErrorCodes.kIsolateMustBePaused) {
379379
// It's possible something else resumed the thread (such as if another
380380
// debugger is attached), we can just continue.
381+
} else if (e.isServiceDisposedError) {
382+
// The VM service connection was terminated, we can silently ignore this
383+
// because we're likely shutting down.
381384
} else if (e.code == RpcErrorCodes.kInternalError &&
382385
e.message.contains('No running isolate (inspector is not set).')) {
383386
// TODO(bkonyi): remove once https://github.com/flutter/flutter/issues/156793
@@ -432,6 +435,9 @@ class IsolateManager {
432435
if (e.code == RpcErrorCodes.kIsolateMustBePaused) {
433436
// It's possible something else resumed the thread (such as if another
434437
// debugger is attached), we can just continue.
438+
} else if (e.isServiceDisposedError) {
439+
// The VM service connection was terminated, we can silently ignore this
440+
// because we're likely shutting down.
435441
} else if (e.code == RpcErrorCodes.kMethodNotFound) {
436442
// Fallback to a regular resume if the DDS service extension isn't
437443
// available:

pkg/dds/lib/src/dap/utils.dart

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
import 'dart:io';
66

77
import 'package:path/path.dart' as path;
8+
import 'package:vm_service/vm_service.dart' as vm;
9+
10+
import '../rpc_error_codes.dart';
811

912
/// Returns whether this URI is something that can be resolved to a file-like
1013
/// URI via the VM Service.
@@ -133,3 +136,25 @@ bool containsVmFlag(List<String> args, String flag) {
133136
}
134137

135138
typedef StackFrameLocation = ({Uri uri, int? line, int? column});
139+
140+
extension RpcErrorExtension on vm.RPCError {
141+
/// Whether this [vm.RPCError] is some kind of "VM Service connection has gone"
142+
/// error that may occur if the VM is shut down.
143+
bool get isServiceDisposedError {
144+
if (code == RpcErrorCodes.kServiceDisappeared ||
145+
code == RpcErrorCodes.kConnectionDisposed) {
146+
return true;
147+
}
148+
149+
if (code == RpcErrorCodes.kExtensionError) {
150+
// Always ignore "client is closed" and "closed with pending request"
151+
// errors because these can always occur during shutdown if we were
152+
// just starting to send (or had just sent) a request.
153+
return message.contains("The client is closed") ||
154+
message.contains("The client closed with pending request") ||
155+
message.contains("Service connection disposed");
156+
}
157+
158+
return false;
159+
}
160+
}

pkg/dds/lib/src/rpc_error_codes.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ abstract class RpcErrorCodes {
2222
static const kInvalidParams = -32602;
2323
static const kInternalError = -32603;
2424

25-
// static const kExtensionError = -32000;
25+
static const kExtensionError = -32000;
2626

2727
static const kConnectionDisposed = -32010;
2828

0 commit comments

Comments
 (0)