Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(335)

Unified Diff: sdk/lib/_internal/lib/isolate_helper.dart

Issue 169703002: Add an error listener on isolates. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rewrite. Now catch all in IsolateContext.eval Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | sdk/lib/isolate/isolate.dart » ('j') | tests/isolate/handle_error2_test.dart » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/_internal/lib/isolate_helper.dart
diff --git a/sdk/lib/_internal/lib/isolate_helper.dart b/sdk/lib/_internal/lib/isolate_helper.dart
index 85d9f2bd0442e559dfcd67a695fed23a543e3243..5b5739b15af1346d1cc54a73c6772d98f6530b39 100644
--- a/sdk/lib/_internal/lib/isolate_helper.dart
+++ b/sdk/lib/_internal/lib/isolate_helper.dart
@@ -89,7 +89,6 @@ void startRootIsolate(entry, args) {
// isolate automatically we try to give them a reasonable context to live in
// by having a "default" isolate (the first one created).
_globalState.currentContext = rootContext;
-
if (entry is _MainFunctionArgs) {
rootContext.eval(() { entry(args); });
} else if (entry is _MainFunctionArgsMessage) {
@@ -271,6 +270,13 @@ class _IsolateContext implements IsolateContext {
final Capability pauseCapability = new Capability();
final Capability terminateCapability = new Capability(); // License to kill.
+ /// Boolean flag set when the initial method of the isolate has been executed.
+ ///
+ /// Used to avoid considering the isolate dead when if it has no open
floitsch 2014/05/15 12:15:25 "when if"
+ /// receive ports and no scheduled timers, because it hasn't had time to
+ /// create them yet.
+ bool initialized = false;
+
// TODO(lrn): Store these in single "PauseState" object, so they don't take
// up as much room when not pausing.
bool isPaused = false;
@@ -290,11 +296,11 @@ class _IsolateContext implements IsolateContext {
var _scheduledControlEvents;
bool _isExecutingEvent = false;
- /** Whether errors are considered fatal. */
- // This doesn't do anything yet. We need to be able to catch uncaught errors
- // (oxymoronically) in order to take lethal action. This is waiting for the
- // same change as the uncaught error listeners.
- bool errorsAreFatal = false;
+ /** Whether uncaught errors are considered fatal. */
+ bool errorsAreFatal = true;
+
+ // Set of ports that listen to uncaught errors.
+ Set<SendPort> errorPorts = new Set();
_IsolateContext() {
this.registerWeak(controlPort._id, controlPort);
@@ -379,6 +385,34 @@ class _IsolateContext implements IsolateContext {
_scheduledControlEvents.addLast(kill);
}
+ void addErrorListener(SendPort port) {
+ errorPorts.add(port);
+ }
+
+ void removeErrorListener(SendPort port) {
+ errorPorts.remove(port);
+ }
+
+ /** Function called with an uncaught error. */
+ void handleUncaughtError(error, StackTrace stackTrace) {
+ // Just print the error if there is no error listener registered.
+ if (errorPorts.isEmpty) {
+ // An uncaught error in the root isolate will terminate the program?
+ if (errorsAreFatal && identical(this, _globalState.rootContext)) {
+ // The error will be rethrown to reach the global scope, so
+ // don't print it.
+ return;
+ }
+ print(error);
floitsch 2014/05/15 12:15:25 I would prefer using console.error when available.
Lasse Reichstein Nielsen 2014/05/19 11:13:37 Done.
+ if (stackTrace != null) print(stackTrace);
+ return;
+ }
+ List message = new List(2)
+ ..[0] = error.toString()
+ ..[1] = (stackTrace == null) ? null : stackTrace.toString();
+ for (SendPort port in errorPorts) port.send(message);
+ }
+
/**
* Run [code] in the context of the isolate represented by [this].
*/
@@ -390,6 +424,15 @@ class _IsolateContext implements IsolateContext {
_isExecutingEvent = true;
try {
result = code();
+ } catch (e, s) {
floitsch 2014/05/15 12:15:25 I'm afraid that this means that we won't have "bre
Lasse Reichstein Nielsen 2014/05/19 11:13:37 True. That may have been one of the reasons for p
+ handleUncaughtError(e, s);
+ if (errorsAreFatal) {
+ kill();
+ // An uncaught error in the root context terminates all isolates.
+ if (identical(this, _globalState.rootContext)) {
+ rethrow;
+ }
+ }
} finally {
_isExecutingEvent = false;
_globalState.currentContext = old;
@@ -437,6 +480,12 @@ class _IsolateContext implements IsolateContext {
case "kill":
handleKill(message[1], message[2]);
break;
+ case "getErrors":
+ addErrorListener(message[1]);
+ break;
+ case "stopErrors":
+ removeErrorListener(message[1]);
+ break;
default:
}
}
@@ -468,7 +517,7 @@ class _IsolateContext implements IsolateContext {
}
void _updateGlobalState() {
- if (ports.length - weakPorts.length > 0 || isPaused) {
+ if (ports.length - weakPorts.length > 0 || isPaused || !initialized) {
_globalState.isolates[id] = this; // indicate this isolate is active
} else {
kill();
@@ -490,6 +539,7 @@ class _IsolateContext implements IsolateContext {
ports.clear();
weakPorts.clear();
_globalState.isolates.remove(id); // indicate this isolate is not active
+ errorPorts.clear();
if (doneHandlers != null) {
for (SendPort port in doneHandlers) {
port.send(null);
@@ -920,6 +970,7 @@ class IsolateNatives {
context.terminateCapability]);
void runStartFunction() {
+ context.initialized = true;
if (!isSpawnUri) {
topLevel(message);
} else if (topLevel is _MainFunctionArgsMessage) {
« no previous file with comments | « no previous file | sdk/lib/isolate/isolate.dart » ('j') | tests/isolate/handle_error2_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698