Skip to content

Commit aeb2581

Browse files
abitofevrythingaam
authored andcommitted
[vm] Use toString when generating stacktrace in isolate error handler
Closes #50438 TEST=tests/lib/isolate/handle_error_stacktrace_test, tests/lib/isolate/handle_exiting_to_string_error_test, tests/lib/isolate/handle_throwing_to_string_error_test Change-Id: I098153ecd65360aa724e25fc52e25368ca27ffe7 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/277341 Reviewed-by: Alexander Aprelev <[email protected]> Reviewed-by: Derek Xu <[email protected]>
1 parent 68eea5b commit aeb2581

File tree

4 files changed

+137
-2
lines changed

4 files changed

+137
-2
lines changed

runtime/vm/isolate.cc

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,15 +1596,25 @@ MessageHandler::MessageStatus IsolateMessageHandler::ProcessUnhandledException(
15961596
} else {
15971597
const Object& exception_str =
15981598
Object::Handle(zone, DartLibraryCalls::ToString(exception));
1599-
if (!exception_str.IsString()) {
1599+
if (exception_str.IsUnwindError()) {
1600+
return StoreError(T, UnwindError::Cast(exception_str));
1601+
} else if (!exception_str.IsString()) {
16001602
exception_cstr = exception.ToCString();
16011603
} else {
16021604
exception_cstr = exception_str.ToCString();
16031605
}
16041606
}
16051607

16061608
const Instance& stacktrace = Instance::Handle(zone, uhe.stacktrace());
1607-
stacktrace_cstr = stacktrace.ToCString();
1609+
const Object& stacktrace_str =
1610+
Object::Handle(zone, DartLibraryCalls::ToString(stacktrace));
1611+
if (stacktrace_str.IsUnwindError()) {
1612+
return StoreError(T, UnwindError::Cast(stacktrace_str));
1613+
} else if (!stacktrace_str.IsString()) {
1614+
stacktrace_cstr = stacktrace.ToCString();
1615+
} else {
1616+
stacktrace_cstr = stacktrace_str.ToCString();
1617+
}
16081618
} else {
16091619
exception_cstr = result.ToErrorCString();
16101620
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
library handle_error_stacktrace_test;
6+
7+
import "dart:isolate";
8+
9+
import "package:expect/expect.dart";
10+
import "package:async_helper/async_helper.dart";
11+
12+
const errorValue = "TEST_ERROR";
13+
const stackTraceValue = "TEST_STACKTRACE";
14+
15+
void isolateMain() {
16+
Error.throwWithStackTrace(errorValue, StackTrace.fromString(stackTraceValue));
17+
}
18+
19+
void main() async {
20+
asyncStart();
21+
22+
var receivedErrors = 0;
23+
final errorPort = ReceivePort();
24+
errorPort.listen((errorAndStack) {
25+
Expect.listEquals([errorValue, stackTraceValue], errorAndStack);
26+
receivedErrors++;
27+
28+
if (receivedErrors == 2) {
29+
errorPort.close();
30+
asyncEnd();
31+
}
32+
});
33+
34+
Isolate.spawn((_) => isolateMain(), null, onError: errorPort.sendPort);
35+
Isolate.spawn(
36+
(_) => isolateMain(),
37+
null,
38+
onError: errorPort.sendPort,
39+
errorsAreFatal: false,
40+
);
41+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
library handle_throwing_to_string_error_test;
6+
7+
import "dart:async";
8+
import "dart:isolate";
9+
10+
import "package:expect/expect.dart";
11+
import "package:async_helper/async_helper.dart";
12+
13+
class ExitingToStringError {
14+
@override
15+
String toString() => Isolate.exit();
16+
}
17+
18+
void isolateMain() {
19+
throw ExitingToStringError();
20+
}
21+
22+
void main() async {
23+
asyncStart();
24+
final errorPort = ReceivePort();
25+
final exitPort = ReceivePort();
26+
Isolate.spawn(
27+
(_) => isolateMain(),
28+
null,
29+
onError: errorPort.sendPort,
30+
onExit: exitPort.sendPort,
31+
);
32+
33+
exitPort.listen((_) {
34+
exitPort.close();
35+
36+
// Give the (hopefully inexistent) error message time to arrive.
37+
Timer(Duration(seconds: 1), () {
38+
errorPort.close();
39+
});
40+
});
41+
42+
Expect.isTrue(await errorPort.isEmpty);
43+
44+
asyncEnd();
45+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
library handle_throwing_to_string_error_test;
6+
7+
import "dart:isolate";
8+
9+
import "package:expect/expect.dart";
10+
import "package:async_helper/async_helper.dart";
11+
12+
class ThrowingToStringError {
13+
@override
14+
String toString() => throw ThrowingToStringError();
15+
}
16+
17+
class ThrowingToStringStackTrace implements StackTrace {
18+
@override
19+
String toString() => throw ThrowingToStringStackTrace();
20+
}
21+
22+
void isolateMain() {
23+
Error.throwWithStackTrace(
24+
ThrowingToStringError(),
25+
ThrowingToStringStackTrace(),
26+
);
27+
}
28+
29+
void main() async {
30+
asyncStart();
31+
final errorPort = ReceivePort();
32+
Isolate.spawn((_) => isolateMain(), null, onError: errorPort.sendPort);
33+
var errorAndStack = await errorPort.first as List<Object?>;
34+
Expect.listEquals([
35+
"Instance of 'ThrowingToStringError'",
36+
"Instance of 'ThrowingToStringStackTrace'",
37+
], errorAndStack);
38+
asyncEnd();
39+
}

0 commit comments

Comments
 (0)