// Copyright (c) 2014, 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=--enable-isolate-groups --experimental-enable-isolate-groups-jit // VMOptions=--no-enable-isolate-groups library handle_error_test; import "dart:isolate"; import "dart:async"; import "package:async_helper/async_helper.dart"; import "package:expect/expect.dart"; isomain1(replyPort) { RawReceivePort port = new RawReceivePort(); port.handler = (v) { switch (v) { case 0: replyPort.send(42); break; case 1: throw new ArgumentError("whoops"); case 2: throw new RangeError.value(37); case 3: port.close(); } }; replyPort.send(port.sendPort); } /// Do Isolate.spawn(entry) and get a sendPort from the isolate that it /// expects commands on. /// The isolate has errors set to non-fatal. /// Returns a list of `[isolate, commandPort]` in a future. Future spawn(entry) { ReceivePort reply = new ReceivePort(); var isolate = Isolate.spawn(entry, reply.sendPort, paused: true); return isolate.then((Isolate isolate) { isolate.setErrorsFatal(false); isolate.resume(isolate.pauseCapability); Future result = reply.first.then((sendPort) { return [isolate, sendPort]; }); return result; }); } main() { asyncStart(); asyncStart(); RawReceivePort reply = new RawReceivePort(null); RawReceivePort reply2 = new RawReceivePort(null); // Create two isolates waiting for commands, with errors non-fatal. Future iso1 = spawn(isomain1); Future iso2 = spawn(isomain1); Future.wait([iso1, iso2]).then((l) { var isolate1 = l[0][0]; var sendPort1 = l[0][1]; var isolate2 = l[1][0]; var sendPort2 = l[1][1]; // Capture errors from one isolate as stream. Stream errors = isolate1.errors; // Broadcast stream, never a done message. int state = 1; var subscription; subscription = errors.listen(null, onError: (error, stack) { switch (state) { case 1: Expect.equals(new ArgumentError("whoops").toString(), "$error"); state++; break; case 2: Expect.equals(new RangeError.value(37).toString(), "$error"); state++; reply.close(); subscription.cancel(); asyncEnd(); break; default: throw "Bad state for error: $state: $error"; } }); // Capture errors from other isolate as raw messages. RawReceivePort errorPort2 = new RawReceivePort(); int state2 = 1; errorPort2.handler = (message) { String error = message[0]; String stack = message[1]; switch (state2) { case 1: Expect.equals(new ArgumentError("whoops").toString(), "$error"); state2++; break; case 2: Expect.equals(new RangeError.value(37).toString(), "$error"); state2++; reply2.close(); isolate2.removeErrorListener(errorPort2.sendPort); errorPort2.close(); asyncEnd(); break; default: throw "Bad state-2 for error: $state: $error"; } }; isolate2.addErrorListener(errorPort2.sendPort); sendPort1.send(0); sendPort2.send(0); sendPort1.send(1); sendPort2.send(1); sendPort1.send(2); sendPort2.send(2); sendPort1.send(3); sendPort2.send(3); }); }