[vm/debugger] Fix notify-debugger-.. for yielding.
For yielding functions (async, sync*, async*) we need to look for annotations on the outer function instead of the synthetic inner function associated with the handler frame. Fixes https://github.com/dart-lang/sdk/issues/45673 TEST=runtime/observatory{,_2}/tests/service{,_2}/notify_debugger_on_exception_yielding_test.dart Bug: https://github.com/dart-lang/sdk/issues/45673 Change-Id: I8b1718b3614852f6f8db98811177b21fe587fea1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/198408 Reviewed-by: Vyacheslav Egorov <vegorov@google.com> Commit-Queue: Clement Skau <cskau@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
f53af0d445
commit
69ebb404e7
@@ -0,0 +1,64 @@
|
||||
// Copyright (c) 2021, 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=--verbose_debug
|
||||
|
||||
// See: https://github.com/dart-lang/sdk/issues/45673
|
||||
|
||||
import 'test_helper.dart';
|
||||
import 'service_test_common.dart';
|
||||
|
||||
const int LINE_A = 19;
|
||||
const int LINE_B = 29;
|
||||
const int LINE_C = 39;
|
||||
|
||||
@pragma('vm:notify-debugger-on-exception')
|
||||
Future<void> throwFromAsync() async {
|
||||
try {
|
||||
throw 'Throw from throwFromAsync'; // LINE_A
|
||||
} catch (e) {
|
||||
// Ignore. Internals will notify debugger.
|
||||
}
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
@pragma('vm:notify-debugger-on-exception')
|
||||
Stream<int> throwFromAsyncStar() async* {
|
||||
try {
|
||||
throw 'Throw from throwFromAsyncStar'; // LINE_B
|
||||
} catch (e) {
|
||||
// Ignore. Internals will notify debugger.
|
||||
}
|
||||
yield 13;
|
||||
}
|
||||
|
||||
@pragma('vm:notify-debugger-on-exception')
|
||||
Iterable<int> throwFromSyncStar() sync* {
|
||||
try {
|
||||
throw 'Throw from throwFromSyncStar'; // LINE_C
|
||||
} catch (e) {
|
||||
// Ignore. Internals will notify debugger.
|
||||
}
|
||||
yield 7;
|
||||
}
|
||||
|
||||
testMain() async {
|
||||
throwFromAsync();
|
||||
await for (var e in throwFromAsyncStar()) {/*ignore*/}
|
||||
for (var e in throwFromSyncStar()) {/*ignore*/}
|
||||
}
|
||||
|
||||
final tests = <IsolateTest>[
|
||||
hasStoppedWithUnhandledException,
|
||||
stoppedAtLine(LINE_A),
|
||||
resumeIsolate,
|
||||
hasStoppedWithUnhandledException,
|
||||
stoppedAtLine(LINE_B),
|
||||
resumeIsolate,
|
||||
hasStoppedWithUnhandledException,
|
||||
stoppedAtLine(LINE_C),
|
||||
];
|
||||
|
||||
main([args = const <String>[]]) => runIsolateTests(args, tests,
|
||||
testeeConcurrent: testMain, pause_on_unhandled_exceptions: true);
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright (c) 2021, 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=--verbose_debug
|
||||
|
||||
// See: https://github.com/dart-lang/sdk/issues/45673
|
||||
|
||||
import 'test_helper.dart';
|
||||
import 'service_test_common.dart';
|
||||
|
||||
const int LINE_A = 19;
|
||||
const int LINE_B = 29;
|
||||
const int LINE_C = 39;
|
||||
|
||||
@pragma('vm:notify-debugger-on-exception')
|
||||
Future<void> throwFromAsync() async {
|
||||
try {
|
||||
throw 'Throw from throwFromAsync'; // LINE_A
|
||||
} catch (e) {
|
||||
// Ignore. Internals will notify debugger.
|
||||
}
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
@pragma('vm:notify-debugger-on-exception')
|
||||
Stream<int> throwFromAsyncStar() async* {
|
||||
try {
|
||||
throw 'Throw from throwFromAsyncStar'; // LINE_B
|
||||
} catch (e) {
|
||||
// Ignore. Internals will notify debugger.
|
||||
}
|
||||
yield 13;
|
||||
}
|
||||
|
||||
@pragma('vm:notify-debugger-on-exception')
|
||||
Iterable<int> throwFromSyncStar() sync* {
|
||||
try {
|
||||
throw 'Throw from throwFromSyncStar'; // LINE_C
|
||||
} catch (e) {
|
||||
// Ignore. Internals will notify debugger.
|
||||
}
|
||||
yield 7;
|
||||
}
|
||||
|
||||
testMain() async {
|
||||
throwFromAsync();
|
||||
await for (var e in throwFromAsyncStar()) {/*ignore*/}
|
||||
for (var e in throwFromSyncStar()) {/*ignore*/}
|
||||
}
|
||||
|
||||
final tests = <IsolateTest>[
|
||||
hasStoppedWithUnhandledException,
|
||||
stoppedAtLine(LINE_A),
|
||||
resumeIsolate,
|
||||
hasStoppedWithUnhandledException,
|
||||
stoppedAtLine(LINE_B),
|
||||
resumeIsolate,
|
||||
hasStoppedWithUnhandledException,
|
||||
stoppedAtLine(LINE_C),
|
||||
];
|
||||
|
||||
main([args = const <String>[]]) => runIsolateTests(args, tests,
|
||||
testeeConcurrent: testMain, pause_on_unhandled_exceptions: true);
|
||||
+17
-1
@@ -2248,11 +2248,27 @@ bool Debugger::ShouldPauseOnException(DebuggerStackTrace* stack_trace,
|
||||
// it will be caught once we unwind the stack.
|
||||
return true;
|
||||
}
|
||||
|
||||
auto& handler_function = Function::Handle(handler_frame->function().ptr());
|
||||
// If the handler function is an synthetic inner function, we need to look for
|
||||
// the annotations on the outer function.
|
||||
if (handler_function.IsAsyncClosure()) {
|
||||
// async :async_op
|
||||
handler_function = handler_function.parent_function();
|
||||
} else if (handler_frame->function().IsAsyncGenClosure()) {
|
||||
// async* :async_op
|
||||
handler_function = handler_function.parent_function();
|
||||
} else if (handler_frame->function().IsSyncGenClosure()) {
|
||||
// sync* :sync_op + :sync_op_gen
|
||||
handler_function = handler_function.parent_function();
|
||||
handler_function = handler_function.parent_function();
|
||||
}
|
||||
|
||||
// If handler_frame's function is annotated with
|
||||
// @pragma('vm:notify-debugger-on-exception'), we specifically want to notify
|
||||
// the debugger of this otherwise ignored exception.
|
||||
if (Library::FindPragma(Thread::Current(), /*only_core=*/false,
|
||||
handler_frame->function(),
|
||||
handler_function,
|
||||
Symbols::vm_notify_debugger_on_exception())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user