Unverified Commit 33fd4f15 authored by Anna Gringauze's avatar Anna Gringauze Committed by GitHub

Fix race causing null dereference on getStack in web_tool_tests and CI flakes (#87278)

parent 26c30fe2
...@@ -250,17 +250,20 @@ abstract class FlutterTestDriver { ...@@ -250,17 +250,20 @@ abstract class FlutterTestDriver {
// This method isn't racy. If the isolate is already paused, // This method isn't racy. If the isolate is already paused,
// it will immediately return. // it will immediately return.
Future<Isolate> waitForPause() async { Future<Isolate> waitForPause() => waitForDebugEvent('Pause');
Future<Isolate> waitForResume() => waitForDebugEvent('Resume');
Future<Isolate> waitForDebugEvent(String kind) async {
return _timeoutWithMessages<Isolate>( return _timeoutWithMessages<Isolate>(
() async { () async {
final String flutterIsolate = await _getFlutterIsolateId(); final String flutterIsolate = await _getFlutterIsolateId();
final Completer<Event> pauseEvent = Completer<Event>(); final Completer<Event> pauseEvent = Completer<Event>();
// Start listening for pause events. // Start listening for events containing 'kind'.
final StreamSubscription<Event> pauseSubscription = _vmService.onDebugEvent final StreamSubscription<Event> pauseSubscription = _vmService.onDebugEvent
.where((Event event) { .where((Event event) {
return event.isolate.id == flutterIsolate return event.isolate.id == flutterIsolate
&& event.kind.startsWith('Pause'); && event.kind.startsWith(kind);
}) })
.listen((Event event) { .listen((Event event) {
if (!pauseEvent.isCompleted) { if (!pauseEvent.isCompleted) {
...@@ -268,14 +271,14 @@ abstract class FlutterTestDriver { ...@@ -268,14 +271,14 @@ abstract class FlutterTestDriver {
} }
}); });
// But also check if the isolate was already paused (only after we've set // But also check if the isolate was already at the stae we need (only after we've
// up the subscription) to avoid races. If it was paused, we don't need to wait // set up the subscription) to avoid races. If it was paused, we don't need to wait
// for the event. // for the event.
final Isolate isolate = await _vmService.getIsolate(flutterIsolate); final Isolate isolate = await _vmService.getIsolate(flutterIsolate);
if (isolate.pauseEvent.kind.startsWith('Pause')) { if (isolate.pauseEvent.kind.startsWith(kind)) {
_debugPrint('Isolate was already paused (${isolate.pauseEvent.kind}).'); _debugPrint('Isolate was already at "$kind" (${isolate.pauseEvent.kind}).');
} else { } else {
_debugPrint('Isolate is not already paused, waiting for event to arrive...'); _debugPrint('Waiting for "$kind" event to arrive...');
await pauseEvent.future; await pauseEvent.future;
} }
...@@ -284,7 +287,7 @@ abstract class FlutterTestDriver { ...@@ -284,7 +287,7 @@ abstract class FlutterTestDriver {
return getFlutterIsolate(); return getFlutterIsolate();
}, },
task: 'Waiting for isolate to pause', task: 'Waiting for isolate to $kind',
); );
} }
...@@ -312,6 +315,7 @@ abstract class FlutterTestDriver { ...@@ -312,6 +315,7 @@ abstract class FlutterTestDriver {
() async => _vmService.resume(await _getFlutterIsolateId(), step: step), () async => _vmService.resume(await _getFlutterIsolateId(), step: step),
task: 'Resuming isolate (step=$step)', task: 'Resuming isolate (step=$step)',
); );
await waitForResume();
return waitForNextPause ? waitForPause() : null; return waitForNextPause ? waitForPause() : null;
} }
......
...@@ -174,7 +174,7 @@ void main() { ...@@ -174,7 +174,7 @@ void main() {
Future<void> failToEvaluateExpression(FlutterTestDriver flutter) async { Future<void> failToEvaluateExpression(FlutterTestDriver flutter) async {
await expectLater( await expectLater(
() => flutter.evaluateInFrame('"test"'), flutter.evaluateInFrame('"test"'),
throwsA(isA<RPCError>().having( throwsA(isA<RPCError>().having(
(RPCError error) => error.message, (RPCError error) => error.message,
'message', 'message',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment