Restore "Avoid to run dart code during paused_on_exit"

This restores 20066b625a
That was reverted in ea3526344a
Related https://github.com/dart-lang/sdk/issues/30555

R=rmacnak@google.com

Review-Url: https://codereview.chromium.org/3006743003 .
This commit is contained in:
Carlo Bernaschina 2017-08-29 13:02:02 -07:00
parent c65d94d440
commit cdd3f4f9e5
3 changed files with 157 additions and 11 deletions

View file

@ -9,4 +9,5 @@ analyzer:
- tests/service/developer_extension_test.dart
- tests/service/evaluate_activation_in_method_class_test.dart
- tests/service/get_isolate_after_language_error_test.dart
- tests/service/get_user_level_retaining_path_rpc_test.dart
- tests/service/pause_on_unhandled_async_exceptions_test.dart

View file

@ -0,0 +1,136 @@
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// VMOptions=--error_on_bad_type --error_on_bad_override
import 'dart:async';
import 'dart:developer';
import 'package:observatory/service_io.dart';
import 'package:unittest/unittest.dart';
import 'service_test_common.dart';
import 'test_helper.dart';
import "dart:isolate" as dart;
void isolate(dart.SendPort port) {
dart.RawReceivePort receive = new dart.RawReceivePort((_) {
debugger();
throw new Exception();
});
port.send(receive.sendPort);
}
void test() {
dart.RawReceivePort receive = new dart.RawReceivePort((port) {
debugger();
port.send(null);
debugger();
port.send(null);
debugger();
});
dart.Isolate.spawn(isolate, receive.sendPort);
}
var tests = [
(VM vm) async {
await vm.load();
bool started = false;
int step = 0;
var completer = new Completer();
var sub;
await hasPausedAtStart(vm.isolates[0]);
sub = await vm.listenEventStream("Debug", (ServiceEvent c) {
switch (step) {
case 0:
expect(c.kind, equals("Resume"),
reason: "First isolate should resume");
expect(c.isolate.id, equals(vm.isolates[0].id),
reason: "First isolate should resume");
break;
case 1:
expect(c.kind, equals("PauseStart"),
reason: "Second isolate should pause on start");
expect(c.isolate.id, equals(vm.isolates[1].id),
reason: "Second isolate should pause on start");
vm.isolates[1].resume();
break;
case 2:
expect(c.kind, equals("Resume"),
reason: "Second isolate should resume");
expect(c.isolate.id, equals(vm.isolates[1].id),
reason: "Second isolate should resume");
break;
case 3:
expect(c.kind, equals("PauseBreakpoint"),
reason: "First isolate should stop at debugger()");
expect(c.isolate.id, equals(vm.isolates[0].id),
reason: "First isolate should stop at debugger()");
vm.isolates[0].resume();
break;
case 4:
expect(c.kind, equals("Resume"),
reason: "First isolate should resume (1)");
expect(c.isolate.id, equals(vm.isolates[0].id),
reason: "First isolate should resume (1)");
break;
case 5:
expect(c.kind, equals("PauseBreakpoint"),
reason: "First & Second isolate should stop at debugger()");
break;
case 6:
expect(c.kind, equals("PauseBreakpoint"),
reason: "First & Second isolate should stop at debugger()");
vm.isolates[1].resume();
break;
case 7:
expect(c.kind, equals("Resume"),
reason: "Second isolate should resume before the exception");
expect(c.isolate.id, equals(vm.isolates[1].id),
reason: "Second isolate should resume before the exception");
break;
case 8:
expect(c.kind, equals("PauseExit"),
reason: "Second isolate should exit at the exception");
expect(c.isolate.id, equals(vm.isolates[1].id),
reason: "Second isolate should exit at the exception");
vm.isolates[0].resume();
break;
case 9:
expect(c.kind, equals("Resume"),
reason: "First isolate should resume after the exception");
expect(c.isolate.id, equals(vm.isolates[0].id),
reason: "First isolate should resume after the exception");
break;
case 10:
expect(c.kind, equals("PauseBreakpoint"),
reason: "First isolate "
"should stop at debugger() after exception.\n"
"Probably the second resumed even though it was not expect "
"to do it.");
expect(c.isolate.id, equals(vm.isolates[0].id),
reason: "First "
"isolate should stop at debugger() after exception.\n"
"Probably the second resumed even though it was not expect "
"to do it.");
completer.complete();
break;
default:
expect(false, isTrue,
reason: "Shouldn't get here, the second "
"isolate resumed even though it was not expect to do it");
break;
}
step++;
});
vm.isolates[0].resume();
await completer.future;
// We wait 1 second to account for delays in the service protocol.
// A late message can still arrive.
await new Future.delayed(const Duration(seconds: 1));
// No fails, tear down the stream.
sub.cancel();
}
];
main(args) async => runVMTests(args, tests,
pause_on_start: true, pause_on_exit: true, testeeConcurrent: test);

View file

@ -346,7 +346,18 @@ void MessageHandler::TaskCallback() {
PausedOnStartLocked(&ml, false);
}
}
#endif
if (is_paused_on_exit()) {
status = HandleMessages(&ml, false, false);
if (ShouldPauseOnExit(status)) {
// Still paused.
ASSERT(oob_queue_->IsEmpty());
task_ = NULL; // No task in queue.
return;
} else {
PausedOnExitLocked(&ml, false);
}
}
#endif // !defined(PRODUCT)
if (status == kOK) {
if (start_callback_) {
@ -373,17 +384,15 @@ void MessageHandler::TaskCallback() {
if (status != kOK || !HasLivePorts()) {
#if !defined(PRODUCT)
if (ShouldPauseOnExit(status)) {
if (!is_paused_on_exit()) {
if (FLAG_trace_service_pause_events) {
OS::PrintErr(
"Isolate %s paused before exiting. "
"Use the Observatory to release it.\n",
name());
}
PausedOnExitLocked(&ml, true);
// More messages may have come in while we released the monitor.
status = HandleMessages(&ml, false, false);
if (FLAG_trace_service_pause_events) {
OS::PrintErr(
"Isolate %s paused before exiting. "
"Use the Observatory to release it.\n",
name());
}
PausedOnExitLocked(&ml, true);
// More messages may have come in while we released the monitor.
status = HandleMessages(&ml, false, false);
if (ShouldPauseOnExit(status)) {
// Still paused.
ASSERT(oob_queue_->IsEmpty());