| Index: runtime/vm/debugger.cc
|
| diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
|
| index ca49376e9b6c08a463fa377e83fa17817d6aea17..6ec2bbd2df14fdde21b5b34f699b6114a040c1aa 100644
|
| --- a/runtime/vm/debugger.cc
|
| +++ b/runtime/vm/debugger.cc
|
| @@ -42,6 +42,8 @@ DEFINE_FLAG(bool, steal_breakpoints, false,
|
| "handler instead. This handler dispatches breakpoints to "
|
| "the VM service.");
|
|
|
| +DECLARE_FLAG(bool, trace_isolates);
|
| +
|
|
|
| Debugger::EventHandler* Debugger::event_handler_ = NULL;
|
|
|
| @@ -320,8 +322,9 @@ void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) {
|
| ASSERT(event.isolate_id() != ILLEGAL_ISOLATE_ID);
|
| if (type == DebuggerEvent::kIsolateInterrupted) {
|
| DebuggerStackTrace* trace = CollectStackTrace();
|
| - ASSERT(trace->Length() > 0);
|
| - event.set_top_frame(trace->FrameAt(0));
|
| + if (trace->Length() > 0) {
|
| + event.set_top_frame(trace->FrameAt(0));
|
| + }
|
| ASSERT(stack_trace_ == NULL);
|
| stack_trace_ = trace;
|
| resume_action_ = kContinue;
|
| @@ -335,11 +338,27 @@ void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) {
|
| }
|
|
|
|
|
| -void Debugger::SignalIsolateInterrupted() {
|
| +RawError* Debugger::SignalIsolateInterrupted() {
|
| if (HasEventHandler()) {
|
| - Debugger* debugger = Isolate::Current()->debugger();
|
| - debugger->SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted);
|
| + SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted);
|
| + }
|
| + Dart_IsolateInterruptCallback callback = isolate_->InterruptCallback();
|
| + if (callback != NULL) {
|
| + if (!(*callback)()) {
|
| + if (FLAG_trace_isolates) {
|
| + OS::Print("[!] Embedder api: terminating isolate:\n"
|
| + "\tisolate: %s\n", isolate_->name());
|
| + }
|
| + const String& msg = String::Handle(String::New("isolate terminated"));
|
| + return UnwindError::New(msg);
|
| + }
|
| }
|
| +
|
| + // If any error occurred while in the debug message loop, return it here.
|
| + const Error& error =
|
| + Error::Handle(isolate_, isolate_->object_store()->sticky_error());
|
| + isolate_->object_store()->clear_sticky_error();
|
| + return error.raw();
|
| }
|
|
|
|
|
| @@ -2553,13 +2572,15 @@ void Debugger::SignalPausedEvent(ActivationFrame* top_frame,
|
| }
|
|
|
|
|
| -void Debugger::DebuggerStepCallback() {
|
| +RawError* Debugger::DebuggerStepCallback() {
|
| ASSERT(isolate_->single_step());
|
| // We can't get here unless the debugger event handler enabled
|
| // single stepping.
|
| ASSERT(HasEventHandler());
|
| // Don't pause recursively.
|
| - if (IsPaused()) return;
|
| + if (IsPaused()) {
|
| + return Error::null();
|
| + }
|
|
|
| // Check whether we are in a Dart function that the user is
|
| // interested in. If we saved the frame pointer of a stack frame
|
| @@ -2575,7 +2596,7 @@ void Debugger::DebuggerStepCallback() {
|
| if (stepping_fp_ > frame->fp()) {
|
| // We are in a callee of the frame we're interested in.
|
| // Ignore this stepping break.
|
| - return;
|
| + return Error::null();
|
| } else if (frame->fp() > stepping_fp_) {
|
| // We returned from the "interesting frame", there can be no more
|
| // stepping breaks for it. Pause at the next appropriate location
|
| @@ -2585,16 +2606,16 @@ void Debugger::DebuggerStepCallback() {
|
| }
|
|
|
| if (!frame->IsDebuggable()) {
|
| - return;
|
| + return Error::null();
|
| }
|
| if (frame->TokenPos() == Scanner::kNoSourcePos) {
|
| - return;
|
| + return Error::null();
|
| }
|
|
|
| // Don't pause for a single step if there is a breakpoint set
|
| // at this location.
|
| if (HasActiveBreakpoint(frame->pc())) {
|
| - return;
|
| + return Error::null();
|
| }
|
|
|
| if (FLAG_verbose_debug) {
|
| @@ -2610,15 +2631,21 @@ void Debugger::DebuggerStepCallback() {
|
| SignalPausedEvent(frame, NULL);
|
| HandleSteppingRequest(stack_trace_);
|
| stack_trace_ = NULL;
|
| +
|
| + // If any error occurred while in the debug message loop, return it here.
|
| + const Error& error =
|
| + Error::Handle(isolate_, isolate_->object_store()->sticky_error());
|
| + isolate_->object_store()->clear_sticky_error();
|
| + return error.raw();
|
| }
|
|
|
|
|
| -void Debugger::SignalBpReached() {
|
| +RawError* Debugger::SignalBpReached() {
|
| // We ignore this breakpoint when the VM is executing code invoked
|
| // by the debugger to evaluate variables values, or when we see a nested
|
| // breakpoint or exception event.
|
| if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) {
|
| - return;
|
| + return Error::null();
|
| }
|
| DebuggerStackTrace* stack_trace = CollectStackTrace();
|
| ASSERT(stack_trace->Length() > 0);
|
| @@ -2672,7 +2699,7 @@ void Debugger::SignalBpReached() {
|
| }
|
|
|
| if (bpt_hit == NULL) {
|
| - return;
|
| + return Error::null();
|
| }
|
|
|
| if (FLAG_verbose_debug) {
|
| @@ -2693,6 +2720,12 @@ void Debugger::SignalBpReached() {
|
| if (cbpt->IsInternal()) {
|
| RemoveInternalBreakpoints();
|
| }
|
| +
|
| + // If any error occurred while in the debug message loop, return it here.
|
| + const Error& error =
|
| + Error::Handle(isolate_, isolate_->object_store()->sticky_error());
|
| + isolate_->object_store()->clear_sticky_error();
|
| + return error.raw();
|
| }
|
|
|
|
|
|
|