| Index: runtime/vm/isolate.cc
|
| diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
|
| index 6089f2db721e057c24b9e4878c09bc754eedab5f..e542420ccd43edcd0e597f7a34a09c246f4dc59f 100644
|
| --- a/runtime/vm/isolate.cc
|
| +++ b/runtime/vm/isolate.cc
|
| @@ -178,7 +178,7 @@ class IsolateMessageHandler : public MessageHandler {
|
|
|
| const char* name() const;
|
| void MessageNotify(Message::Priority priority);
|
| - bool HandleMessage(Message* message);
|
| + MessageStatus HandleMessage(Message* message);
|
| void NotifyPauseOnStart();
|
| void NotifyPauseOnExit();
|
|
|
| @@ -194,7 +194,7 @@ class IsolateMessageHandler : public MessageHandler {
|
| // processing of further events.
|
| RawError* HandleLibMessage(const Array& message);
|
|
|
| - bool ProcessUnhandledException(const Error& result);
|
| + MessageStatus ProcessUnhandledException(const Error& result);
|
| Isolate* isolate_;
|
| };
|
|
|
| @@ -285,7 +285,8 @@ RawError* IsolateMessageHandler::HandleLibMessage(const Array& message) {
|
| break;
|
| }
|
| case Isolate::kKillMsg:
|
| - case Isolate::kInternalKillMsg: {
|
| + case Isolate::kInternalKillMsg:
|
| + case Isolate::kVMRestartMsg: {
|
| // [ OOB, kKillMsg, terminate capability, priority ]
|
| if (message.Length() != 4) return Error::null();
|
| Object& obj = Object::Handle(I, message.At(3));
|
| @@ -293,8 +294,8 @@ RawError* IsolateMessageHandler::HandleLibMessage(const Array& message) {
|
| const intptr_t priority = Smi::Cast(obj).Value();
|
| if (priority == Isolate::kImmediateAction) {
|
| obj = message.At(2);
|
| - // Signal that the isolate should stop execution.
|
| if (I->VerifyTerminateCapability(obj)) {
|
| + // We will kill the current isolate by returning an UnwindError.
|
| if (msg_type == Isolate::kKillMsg) {
|
| const String& msg = String::Handle(String::New(
|
| "isolate terminated by Isolate.kill"));
|
| @@ -302,14 +303,22 @@ RawError* IsolateMessageHandler::HandleLibMessage(const Array& message) {
|
| UnwindError::Handle(UnwindError::New(msg));
|
| error.set_is_user_initiated(true);
|
| return error.raw();
|
| - } else {
|
| - // TODO(turnidge): We should give the message handler a way
|
| - // to detect when an isolate is unwinding.
|
| - I->message_handler()->set_pause_on_start(false);
|
| - I->message_handler()->set_pause_on_exit(false);
|
| + } else if (msg_type == Isolate::kInternalKillMsg) {
|
| const String& msg = String::Handle(String::New(
|
| "isolate terminated by vm"));
|
| return UnwindError::New(msg);
|
| + } else if (msg_type == Isolate::kVMRestartMsg) {
|
| + // If this is the main isolate, this request to restart
|
| + // will be caught and handled in the embedder. Otherwise
|
| + // this unwind error will cause the isolate to exit.
|
| + const String& msg = String::Handle(String::New(
|
| + "isolate terminated for vm restart"));
|
| + const UnwindError& error =
|
| + UnwindError::Handle(UnwindError::New(msg));
|
| + error.set_is_vm_restart(true);
|
| + return error.raw();
|
| + } else {
|
| + UNREACHABLE();
|
| }
|
| } else {
|
| return Error::null();
|
| @@ -421,7 +430,8 @@ void IsolateMessageHandler::MessageNotify(Message::Priority priority) {
|
| }
|
|
|
|
|
| -bool IsolateMessageHandler::HandleMessage(Message* message) {
|
| +MessageHandler::MessageStatus IsolateMessageHandler::HandleMessage(
|
| + Message* message) {
|
| ASSERT(IsCurrentIsolate());
|
| Thread* thread = Thread::Current();
|
| StackZone stack_zone(thread);
|
| @@ -450,7 +460,7 @@ bool IsolateMessageHandler::HandleMessage(Message* message) {
|
| } else {
|
| delete message;
|
| }
|
| - return true;
|
| + return kOK;
|
| }
|
| }
|
|
|
| @@ -474,7 +484,7 @@ bool IsolateMessageHandler::HandleMessage(Message* message) {
|
| Instance& msg = Instance::Handle(zone);
|
| msg ^= msg_obj.raw(); // Can't use Instance::Cast because may be null.
|
|
|
| - bool success = true;
|
| + MessageStatus status = kOK;
|
| if (message->IsOOB()) {
|
| // OOB messages are expected to be fixed length arrays where the first
|
| // element is a Smi describing the OOB destination. Messages that do not
|
| @@ -492,7 +502,7 @@ bool IsolateMessageHandler::HandleMessage(Message* message) {
|
| case Message::kIsolateLibOOBMsg: {
|
| const Error& error = Error::Handle(HandleLibMessage(oob_msg));
|
| if (!error.IsNull()) {
|
| - success = ProcessUnhandledException(error);
|
| + status = ProcessUnhandledException(error);
|
| }
|
| break;
|
| }
|
| @@ -519,7 +529,7 @@ bool IsolateMessageHandler::HandleMessage(Message* message) {
|
| (Smi::Cast(oob_tag).Value() == Message::kDelayedIsolateLibOOBMsg)) {
|
| const Error& error = Error::Handle(HandleLibMessage(msg_arr));
|
| if (!error.IsNull()) {
|
| - success = ProcessUnhandledException(error);
|
| + status = ProcessUnhandledException(error);
|
| }
|
| }
|
| }
|
| @@ -528,22 +538,22 @@ bool IsolateMessageHandler::HandleMessage(Message* message) {
|
| const Object& result = Object::Handle(zone,
|
| DartLibraryCalls::HandleMessage(msg_handler, msg));
|
| if (result.IsError()) {
|
| - success = ProcessUnhandledException(Error::Cast(result));
|
| + status = ProcessUnhandledException(Error::Cast(result));
|
| } else {
|
| ASSERT(result.IsNull());
|
| }
|
| }
|
| delete message;
|
| - if (success) {
|
| + if (status == kOK) {
|
| const Object& result =
|
| Object::Handle(zone, I->InvokePendingServiceExtensionCalls());
|
| if (result.IsError()) {
|
| - success = ProcessUnhandledException(Error::Cast(result));
|
| + status = ProcessUnhandledException(Error::Cast(result));
|
| } else {
|
| ASSERT(result.IsNull());
|
| }
|
| }
|
| - return success;
|
| + return status;
|
| }
|
|
|
|
|
| @@ -587,7 +597,25 @@ bool IsolateMessageHandler::IsCurrentIsolate() const {
|
| }
|
|
|
|
|
| -bool IsolateMessageHandler::ProcessUnhandledException(const Error& result) {
|
| +static MessageHandler::MessageStatus StoreError(Isolate* isolate,
|
| + const Error& error) {
|
| + isolate->object_store()->set_sticky_error(error);
|
| + if (error.IsUnwindError()) {
|
| + const UnwindError& unwind = UnwindError::Cast(error);
|
| + if (!unwind.is_user_initiated()) {
|
| + if (unwind.is_vm_restart()) {
|
| + return MessageHandler::kRestart;
|
| + } else {
|
| + return MessageHandler::kShutdown;
|
| + }
|
| + }
|
| + }
|
| + return MessageHandler::kError;
|
| +}
|
| +
|
| +
|
| +MessageHandler::MessageStatus IsolateMessageHandler::ProcessUnhandledException(
|
| + const Error& result) {
|
| // Notify the debugger about specific unhandled exceptions which are withheld
|
| // when being thrown.
|
| if (result.IsUnhandledException()) {
|
| @@ -631,9 +659,9 @@ bool IsolateMessageHandler::ProcessUnhandledException(const Error& result) {
|
| exc_str = String::New(result.ToErrorCString());
|
| }
|
| if (result.IsUnwindError()) {
|
| - // Unwind errors are always fatal and don't notify listeners.
|
| - I->object_store()->set_sticky_error(result);
|
| - return false;
|
| + // When unwinding we don't notify error listeners and we ignore
|
| + // whether errors are fatal for the current isolate.
|
| + return StoreError(I, result);
|
| } else {
|
| bool has_listener = I->NotifyErrorListeners(exc_str, stacktrace_str);
|
| if (I->ErrorsFatal()) {
|
| @@ -642,10 +670,10 @@ bool IsolateMessageHandler::ProcessUnhandledException(const Error& result) {
|
| } else {
|
| I->object_store()->set_sticky_error(result);
|
| }
|
| - return false;
|
| + return kError;
|
| }
|
| }
|
| - return true;
|
| + return kOK;
|
| }
|
|
|
|
|
| @@ -1308,13 +1336,7 @@ bool Isolate::NotifyErrorListeners(const String& msg,
|
| }
|
|
|
|
|
| -static void StoreError(Isolate* isolate, const Object& obj) {
|
| - ASSERT(obj.IsError());
|
| - isolate->object_store()->set_sticky_error(Error::Cast(obj));
|
| -}
|
| -
|
| -
|
| -static bool RunIsolate(uword parameter) {
|
| +static MessageHandler::MessageStatus RunIsolate(uword parameter) {
|
| Isolate* isolate = reinterpret_cast<Isolate*>(parameter);
|
| IsolateSpawnState* state = NULL;
|
| Thread* thread = Thread::Current();
|
| @@ -1348,15 +1370,19 @@ static bool RunIsolate(uword parameter) {
|
|
|
| if (!ClassFinalizer::ProcessPendingClasses()) {
|
| // Error is in sticky error already.
|
| - return false;
|
| +#if defined(DEBUG)
|
| + const Error& error =
|
| + Error::Handle(isolate->object_store()->sticky_error());
|
| + ASSERT(!error.IsUnwindError());
|
| +#endif
|
| + return MessageHandler::kError;
|
| }
|
|
|
| Object& result = Object::Handle();
|
| result = state->ResolveFunction();
|
| bool is_spawn_uri = state->is_spawn_uri();
|
| if (result.IsError()) {
|
| - StoreError(isolate, result);
|
| - return false;
|
| + return StoreError(isolate, Error::Cast(result));
|
| }
|
| ASSERT(result.IsFunction());
|
| Function& func = Function::Handle(isolate);
|
| @@ -1411,11 +1437,10 @@ static bool RunIsolate(uword parameter) {
|
|
|
| result = DartEntry::InvokeFunction(entry_point, args);
|
| if (result.IsError()) {
|
| - StoreError(isolate, result);
|
| - return false;
|
| + return StoreError(isolate, Error::Cast(result));
|
| }
|
| }
|
| - return true;
|
| + return MessageHandler::kOK;
|
| }
|
|
|
|
|
| @@ -1474,8 +1499,9 @@ RawError* Isolate::HandleInterrupts() {
|
| }
|
| }
|
| if ((interrupt_bits & kMessageInterrupt) != 0) {
|
| - bool ok = message_handler()->HandleOOBMessages();
|
| - if (!ok) {
|
| + MessageHandler::MessageStatus status =
|
| + message_handler()->HandleOOBMessages();
|
| + if (status != MessageHandler::kOK) {
|
| // False result from HandleOOBMessages signals that the isolate should
|
| // be terminating.
|
| if (FLAG_trace_isolates) {
|
| @@ -1483,8 +1509,8 @@ RawError* Isolate::HandleInterrupts() {
|
| "\tisolate: %s\n", name());
|
| }
|
| const Error& error = Error::Handle(object_store()->sticky_error());
|
| + ASSERT(!error.IsNull() && error.IsUnwindError());
|
| object_store()->clear_sticky_error();
|
| - ASSERT(!error.IsNull());
|
| return error.raw();
|
| }
|
| }
|
| @@ -2293,7 +2319,7 @@ C* Isolate::AllocateReusableHandle() {
|
| }
|
|
|
|
|
| -void Isolate::KillLocked() {
|
| +void Isolate::KillLocked(LibMsgId msg_id) {
|
| Dart_CObject kill_msg;
|
| Dart_CObject* list_values[4];
|
| kill_msg.type = Dart_CObject_kArray;
|
| @@ -2307,7 +2333,7 @@ void Isolate::KillLocked() {
|
|
|
| Dart_CObject msg_type;
|
| msg_type.type = Dart_CObject_kInt32;
|
| - msg_type.value.as_int32 = Isolate::kInternalKillMsg;
|
| + msg_type.value.as_int32 = msg_id;
|
| list_values[1] = &msg_type;
|
|
|
| Dart_CObject cap;
|
| @@ -2338,10 +2364,11 @@ void Isolate::KillLocked() {
|
|
|
| class IsolateKillerVisitor : public IsolateVisitor {
|
| public:
|
| - IsolateKillerVisitor() : target_(NULL) {}
|
| + explicit IsolateKillerVisitor(Isolate::LibMsgId msg_id)
|
| + : target_(NULL), msg_id_(msg_id) {}
|
|
|
| - explicit IsolateKillerVisitor(Isolate* isolate)
|
| - : target_(isolate) {
|
| + IsolateKillerVisitor(Isolate* isolate, Isolate::LibMsgId msg_id)
|
| + : target_(isolate), msg_id_(msg_id) {
|
| ASSERT(isolate != Dart::vm_isolate());
|
| }
|
|
|
| @@ -2350,7 +2377,7 @@ class IsolateKillerVisitor : public IsolateVisitor {
|
| void VisitIsolate(Isolate* isolate) {
|
| ASSERT(isolate != NULL);
|
| if (ShouldKill(isolate)) {
|
| - isolate->KillLocked();
|
| + isolate->KillLocked(msg_id_);
|
| }
|
| }
|
|
|
| @@ -2365,17 +2392,18 @@ class IsolateKillerVisitor : public IsolateVisitor {
|
| }
|
|
|
| Isolate* target_;
|
| + Isolate::LibMsgId msg_id_;
|
| };
|
|
|
|
|
| -void Isolate::KillAllIsolates() {
|
| - IsolateKillerVisitor visitor;
|
| +void Isolate::KillAllIsolates(LibMsgId msg_id) {
|
| + IsolateKillerVisitor visitor(msg_id);
|
| VisitIsolates(&visitor);
|
| }
|
|
|
|
|
| -void Isolate::KillIfExists(Isolate* isolate) {
|
| - IsolateKillerVisitor visitor(isolate);
|
| +void Isolate::KillIfExists(Isolate* isolate, LibMsgId msg_id) {
|
| + IsolateKillerVisitor visitor(isolate, msg_id);
|
| VisitIsolates(&visitor);
|
| }
|
|
|
|
|