@@ -127,27 +127,6 @@ class VMServiceFlutterDriver extends FlutterDriver {
127
127
128
128
driver._dartVmReconnectUrl = dartVmServiceUrl;
129
129
130
- // Attempts to resume the isolate, but does not crash if it fails because
131
- // the isolate is already resumed. There could be a race with other tools,
132
- // such as a debugger, any of which could have resumed the isolate.
133
- Future <dynamic > resumeLeniently () {
134
- _log ('Attempting to resume isolate' );
135
- return isolate.resume ().catchError ((dynamic e) {
136
- const int vmMustBePausedCode = 101 ;
137
- if (e is rpc.RpcException && e.code == vmMustBePausedCode) {
138
- // No biggie; something else must have resumed the isolate
139
- _log (
140
- 'Attempted to resume an already resumed isolate. This may happen '
141
- 'when we lose a race with another tool (usually a debugger) that '
142
- 'is connected to the same isolate.'
143
- );
144
- } else {
145
- // Failed to resume due to another reason. Fail hard.
146
- throw e;
147
- }
148
- });
149
- }
150
-
151
130
/// Waits for a signal from the VM service that the extension is registered.
152
131
///
153
132
/// Looks at the list of loaded extensions for the current [isolateRef] , as
@@ -195,19 +174,26 @@ class VMServiceFlutterDriver extends FlutterDriver {
195
174
});
196
175
}
197
176
177
+ // The Dart VM may be running with --pause-isolates-on-start.
178
+ // Set a listener to unpause new isolates as they are ready to run,
179
+ // otherwise they'll hang indefinitely.
180
+ client.onIsolateRunnable.listen ((VMIsolateRef isolateRef) async {
181
+ _resumeLeniently (await isolateRef.load ());
182
+ });
183
+
198
184
// Attempt to resume isolate if it was paused
199
185
if (isolate.pauseEvent is VMPauseStartEvent ) {
200
186
_log ('Isolate is paused at start.' );
201
187
202
- await resumeLeniently ( );
188
+ await _resumeLeniently (isolate );
203
189
} else if (isolate.pauseEvent is VMPauseExitEvent ||
204
190
isolate.pauseEvent is VMPauseBreakpointEvent ||
205
191
isolate.pauseEvent is VMPauseExceptionEvent ||
206
192
isolate.pauseEvent is VMPauseInterruptedEvent ) {
207
193
// If the isolate is paused for any other reason, assume the extension is
208
194
// already there.
209
195
_log ('Isolate is paused mid-flight.' );
210
- await resumeLeniently ( );
196
+ await _resumeLeniently (isolate );
211
197
} else if (isolate.pauseEvent is VMResumeEvent ) {
212
198
_log ('Isolate is not paused. Assuming application is ready.' );
213
199
} else {
@@ -240,6 +226,27 @@ class VMServiceFlutterDriver extends FlutterDriver {
240
226
return driver;
241
227
}
242
228
229
+ /// Attempts to resume the isolate, but does not crash if it fails because
230
+ /// the isolate is already resumed. There could be a race with other tools,
231
+ /// such as a debugger, any of which could have resumed the isolate.
232
+ static Future <dynamic > _resumeLeniently (VMIsolate isolate) {
233
+ _log ('Attempting to resume isolate' );
234
+ return isolate.resume ().catchError ((dynamic e) {
235
+ const int vmMustBePausedCode = 101 ;
236
+ if (e is rpc.RpcException && e.code == vmMustBePausedCode) {
237
+ // No biggie; something else must have resumed the isolate
238
+ _log (
239
+ 'Attempted to resume an already resumed isolate. This may happen '
240
+ 'when we lose a race with another tool (usually a debugger) that '
241
+ 'is connected to the same isolate.'
242
+ );
243
+ } else {
244
+ // Failed to resume due to another reason. Fail hard.
245
+ throw e;
246
+ }
247
+ });
248
+ }
249
+
243
250
static int _nextDriverId = 0 ;
244
251
245
252
static const String _flutterExtensionMethodName = 'ext.flutter.driver' ;
0 commit comments