Index: runtime/vm/message_handler.cc |
diff --git a/runtime/vm/message_handler.cc b/runtime/vm/message_handler.cc |
index 30194cd5b4ec4a3074f690712f8bca1c2679a0b3..2340b65d766794da64779349e0449d8ab03a63a5 100644 |
--- a/runtime/vm/message_handler.cc |
+++ b/runtime/vm/message_handler.cc |
@@ -61,10 +61,10 @@ MessageHandler::MessageHandler() |
oob_message_handling_allowed_(true), |
live_ports_(0), |
paused_(0), |
- pause_on_start_(false), |
- pause_on_exit_(false), |
- paused_on_start_(false), |
- paused_on_exit_(false), |
+ should_pause_on_start_(false), |
+ should_pause_on_exit_(false), |
+ is_paused_on_start_(false), |
+ is_paused_on_exit_(false), |
paused_timestamp_(-1), |
pool_(NULL), |
task_(NULL), |
@@ -258,6 +258,18 @@ MessageHandler::MessageStatus MessageHandler::HandleNextMessage() { |
} |
+MessageHandler::MessageStatus MessageHandler::HandleAllMessages() { |
+ // We can only call HandleAllMessages when this handler is not |
+ // assigned to a thread pool. |
+ MonitorLocker ml(&monitor_); |
+ ASSERT(pool_ == NULL); |
+#if defined(DEBUG) |
+ CheckAccess(); |
+#endif |
+ return HandleMessages(true, true); |
+} |
+ |
+ |
MessageHandler::MessageStatus MessageHandler::HandleOOBMessages() { |
if (!oob_message_handling_allowed_) { |
return kOK; |
@@ -270,17 +282,33 @@ MessageHandler::MessageStatus MessageHandler::HandleOOBMessages() { |
} |
-bool MessageHandler::HasOOBMessages() { |
- MonitorLocker ml(&monitor_); |
- return !oob_queue_->IsEmpty(); |
+bool MessageHandler::ShouldPauseOnStart(MessageStatus status) const { |
+ Isolate* owning_isolate = isolate(); |
+ if (owning_isolate == NULL) { |
+ return false; |
+ } |
+ // If we are restarting or shutting down, we do not want to honor |
+ // should_pause_on_start or should_pause_on_exit. |
+ return (status != MessageHandler::kRestart && |
+ status != MessageHandler::kShutdown) && |
+ should_pause_on_start() && owning_isolate->is_runnable(); |
} |
-static bool ShouldPause(MessageHandler::MessageStatus status) { |
- // If we are restarting or shutting down, we do not want to honor |
- // pause_on_start or pause_on_exit. |
+bool MessageHandler::ShouldPauseOnExit(MessageStatus status) const { |
+ Isolate* owning_isolate = isolate(); |
+ if (owning_isolate == NULL) { |
+ return false; |
+ } |
return (status != MessageHandler::kRestart && |
- status != MessageHandler::kShutdown); |
+ status != MessageHandler::kShutdown) && |
+ should_pause_on_exit() && owning_isolate->is_runnable(); |
+} |
+ |
+ |
+bool MessageHandler::HasOOBMessages() { |
+ MonitorLocker ml(&monitor_); |
+ return !oob_queue_->IsEmpty(); |
} |
@@ -294,28 +322,19 @@ void MessageHandler::TaskCallback() { |
// all pending OOB messages, or we may miss a request for vm |
// shutdown. |
MonitorLocker ml(&monitor_); |
- if (pause_on_start()) { |
- if (!paused_on_start_) { |
- // Temporarily release the monitor when calling out to |
- // NotifyPauseOnStart. This avoids a dead lock that can occur |
- // when this message handler tries to post a message while a |
- // message is being posted to it. |
- paused_on_start_ = true; |
- paused_timestamp_ = OS::GetCurrentTimeMillis(); |
- monitor_.Exit(); |
- NotifyPauseOnStart(); |
- monitor_.Enter(); |
+ if (ShouldPauseOnStart(kOK)) { |
+ if (!is_paused_on_start()) { |
+ PausedOnStartLocked(true); |
} |
// More messages may have come in before we (re)acquired the monitor. |
status = HandleMessages(false, false); |
- if (ShouldPause(status) && pause_on_start()) { |
+ if (ShouldPauseOnStart(status)) { |
// Still paused. |
ASSERT(oob_queue_->IsEmpty()); |
task_ = NULL; // No task in queue. |
return; |
} else { |
- paused_on_start_ = false; |
- paused_timestamp_ = -1; |
+ PausedOnStartLocked(false); |
} |
} |
@@ -342,33 +361,23 @@ void MessageHandler::TaskCallback() { |
// The isolate exits when it encounters an error or when it no |
// longer has live ports. |
if (status != kOK || !HasLivePorts()) { |
- if (ShouldPause(status) && pause_on_exit()) { |
- if (!paused_on_exit_) { |
+ if (ShouldPauseOnExit(status)) { |
+ if (!is_paused_on_exit()) { |
if (FLAG_trace_service_pause_events) { |
OS::PrintErr("Isolate %s paused before exiting. " |
"Use the Observatory to release it.\n", name()); |
} |
- // Temporarily release the monitor when calling out to |
- // NotifyPauseOnExit. This avoids a dead lock that can |
- // occur when this message handler tries to post a message |
- // while a message is being posted to it. |
- paused_on_exit_ = true; |
- paused_timestamp_ = OS::GetCurrentTimeMillis(); |
- monitor_.Exit(); |
- NotifyPauseOnExit(); |
- monitor_.Enter(); |
- |
+ PausedOnExitLocked(true); |
// More messages may have come in while we released the monitor. |
- HandleMessages(false, false); |
+ status = HandleMessages(false, false); |
} |
- if (ShouldPause(status) && pause_on_exit()) { |
+ if (ShouldPauseOnExit(status)) { |
// Still paused. |
ASSERT(oob_queue_->IsEmpty()); |
task_ = NULL; // No task in queue. |
return; |
} else { |
- paused_on_exit_ = false; |
- paused_timestamp_ = -1; |
+ PausedOnExitLocked(false); |
} |
} |
if (FLAG_trace_isolates) { |
@@ -443,6 +452,74 @@ void MessageHandler::decrement_live_ports() { |
} |
+void MessageHandler::PausedOnStart(bool paused) { |
+ MonitorLocker ml(&monitor_); |
+ PausedOnStartLocked(paused); |
+} |
+ |
+ |
+void MessageHandler::PausedOnStartLocked(bool paused) { |
+ if (paused) { |
+ ASSERT(!is_paused_on_start_); |
+ is_paused_on_start_ = true; |
+ paused_timestamp_ = OS::GetCurrentTimeMillis(); |
+ } else { |
+ ASSERT(is_paused_on_start_); |
+ is_paused_on_start_ = false; |
+ paused_timestamp_ = -1; |
+ } |
+ if (is_paused_on_start_) { |
+ // Temporarily release the monitor when calling out to |
+ // NotifyPauseOnStart. This avoids a dead lock that can occur |
+ // when this message handler tries to post a message while a |
+ // message is being posted to it. |
+ monitor_.Exit(); |
+ NotifyPauseOnStart(); |
+ monitor_.Enter(); |
+ } else { |
+ // Resumed. Clear the resume request of the owning isolate. |
+ Isolate* owning_isolate = isolate(); |
+ if (owning_isolate != NULL) { |
+ owning_isolate->GetAndClearResumeRequest(); |
+ } |
+ } |
+} |
+ |
+ |
+void MessageHandler::PausedOnExit(bool paused) { |
+ MonitorLocker ml(&monitor_); |
+ PausedOnExitLocked(paused); |
+} |
+ |
+ |
+void MessageHandler::PausedOnExitLocked(bool paused) { |
+ if (paused) { |
+ ASSERT(!is_paused_on_exit_); |
+ is_paused_on_exit_ = true; |
+ paused_timestamp_ = OS::GetCurrentTimeMillis(); |
+ } else { |
+ ASSERT(is_paused_on_exit_); |
+ is_paused_on_exit_ = false; |
+ paused_timestamp_ = -1; |
+ } |
+ if (is_paused_on_exit_) { |
+ // Temporarily release the monitor when calling out to |
+ // NotifyPauseOnExit. This avoids a dead lock that can |
+ // occur when this message handler tries to post a message |
+ // while a message is being posted to it. |
+ monitor_.Exit(); |
+ NotifyPauseOnExit(); |
+ monitor_.Enter(); |
+ } else { |
+ // Resumed. Clear the resume request of the owning isolate. |
+ Isolate* owning_isolate = isolate(); |
+ if (owning_isolate != NULL) { |
+ owning_isolate->GetAndClearResumeRequest(); |
+ } |
+ } |
+} |
+ |
+ |
MessageHandler::AcquiredQueues::AcquiredQueues() |
: handler_(NULL) { |
} |