| Index: runtime/vm/service_isolate.cc
|
| diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
|
| index fc9fc4273eb41918f0d42a89b73e8645f91f5859..c9a47c2418d3fd8efe0268813c6e2e544d332988 100644
|
| --- a/runtime/vm/service_isolate.cc
|
| +++ b/runtime/vm/service_isolate.cc
|
| @@ -116,6 +116,7 @@ static Dart_Port ExtractPort(Isolate* isolate, Dart_Handle receivePort) {
|
|
|
|
|
| // These must be kept in sync with service/constants.dart
|
| +#define VM_SERVICE_ISOLATE_EXIT_MESSAGE_ID 0
|
| #define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID 1
|
| #define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID 2
|
|
|
| @@ -134,13 +135,26 @@ static RawArray* MakeServiceControlMessage(Dart_Port port_id, intptr_t code,
|
| }
|
|
|
|
|
| +static RawArray* MakeServiceExitMessage() {
|
| + const Array& list = Array::Handle(Array::New(1));
|
| + ASSERT(!list.IsNull());
|
| + const intptr_t code = VM_SERVICE_ISOLATE_EXIT_MESSAGE_ID;
|
| + const Integer& code_int = Integer::Handle(Integer::New(code));
|
| + list.SetAt(0, code_int);
|
| + return list.raw();
|
| +}
|
| +
|
| +
|
| const char* ServiceIsolate::kName = "vm-service";
|
| Isolate* ServiceIsolate::isolate_ = NULL;
|
| Dart_Port ServiceIsolate::port_ = ILLEGAL_PORT;
|
| Dart_Port ServiceIsolate::load_port_ = ILLEGAL_PORT;
|
| Dart_IsolateCreateCallback ServiceIsolate::create_callback_ = NULL;
|
| +uint8_t* ServiceIsolate::exit_message_ = NULL;
|
| +intptr_t ServiceIsolate::exit_message_length_ = 0;
|
| Monitor* ServiceIsolate::monitor_ = NULL;
|
| bool ServiceIsolate::initializing_ = true;
|
| +bool ServiceIsolate::shutting_down_ = false;
|
|
|
|
|
| class RegisterRunningIsolatesVisitor : public IsolateVisitor {
|
| @@ -279,6 +293,18 @@ class ServiceIsolateNatives : public AllStatic {
|
| Isolate::VisitIsolates(®ister_isolates);
|
| }
|
| }
|
| +
|
| + static void OnExit(Dart_NativeArguments args) {
|
| + NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
|
| + Isolate* isolate = arguments->isolate();
|
| + StackZone zone(isolate);
|
| + HANDLESCOPE(isolate);
|
| + {
|
| + if (FLAG_trace_service) {
|
| + OS::Print("vm-service: processed exit message.\n");
|
| + }
|
| + }
|
| + }
|
| };
|
|
|
|
|
| @@ -298,6 +324,8 @@ static ServiceNativeEntry _ServiceNativeEntries[] = {
|
| ServiceIsolateNatives::SetEventMask},
|
| {"VMService_OnStart", 0,
|
| ServiceIsolateNatives::OnStart },
|
| + {"VMService_OnExit", 0,
|
| + ServiceIsolateNatives::OnExit },
|
| };
|
|
|
|
|
| @@ -434,6 +462,23 @@ bool ServiceIsolate::SendIsolateShutdownMessage() {
|
| }
|
|
|
|
|
| +void ServiceIsolate::SendServiceExitMessage() {
|
| + if (!IsRunning()) {
|
| + return;
|
| + }
|
| + if ((exit_message_ == NULL) || (exit_message_length_ == 0)) {
|
| + return;
|
| + }
|
| + if (FLAG_trace_service) {
|
| + OS::Print("vm-service: sending service exit message.\n");
|
| + }
|
| + PortMap::PostMessage(new Message(port_,
|
| + exit_message_,
|
| + exit_message_length_,
|
| + Message::kNormalPriority));
|
| +}
|
| +
|
| +
|
| void ServiceIsolate::SetServicePort(Dart_Port port) {
|
| MonitorLocker ml(monitor_);
|
| port_ = port;
|
| @@ -506,6 +551,31 @@ void ServiceIsolate::MaybeInjectVMServiceLibrary(Isolate* isolate) {
|
| }
|
|
|
|
|
| +void ServiceIsolate::ConstructExitMessageAndCache(Isolate* isolate) {
|
| + // Construct and cache exit message here so we can send it without needing an
|
| + // isolate.
|
| + StartIsolateScope iso_scope(isolate);
|
| + StackZone zone(isolate);
|
| + HANDLESCOPE(isolate);
|
| + ASSERT(exit_message_ == NULL);
|
| + ASSERT(exit_message_length_ == 0);
|
| + const Array& list = Array::Handle(MakeServiceExitMessage());
|
| + ASSERT(!list.IsNull());
|
| + MessageWriter writer(&exit_message_, &allocator, false);
|
| + writer.WriteMessage(list);
|
| + exit_message_length_ = writer.BytesWritten();
|
| + ASSERT(exit_message_ != NULL);
|
| + ASSERT(exit_message_length_ != 0);
|
| +}
|
| +
|
| +
|
| +void ServiceIsolate::FinishedExiting() {
|
| + MonitorLocker ml(monitor_);
|
| + shutting_down_ = false;
|
| + ml.NotifyAll();
|
| +}
|
| +
|
| +
|
| void ServiceIsolate::FinishedInitializing() {
|
| MonitorLocker ml(monitor_);
|
| initializing_ = false;
|
| @@ -543,6 +613,8 @@ class RunServiceTask : public ThreadPool::Task {
|
|
|
| Isolate::SetCurrent(NULL);
|
|
|
| + ServiceIsolate::ConstructExitMessageAndCache(isolate);
|
| +
|
| RunMain(isolate);
|
|
|
| ServiceIsolate::FinishedInitializing();
|
| @@ -580,6 +652,7 @@ class RunServiceTask : public ThreadPool::Task {
|
| if (FLAG_trace_service) {
|
| OS::Print("vm-service: Shutdown.\n");
|
| }
|
| + ServiceIsolate::FinishedExiting();
|
| }
|
|
|
| void RunMain(Isolate* isolate) {
|
| @@ -642,6 +715,24 @@ void ServiceIsolate::Run() {
|
| }
|
|
|
|
|
| +void ServiceIsolate::Shutdown() {
|
| + if (!IsRunning()) {
|
| + return;
|
| + }
|
| + {
|
| + MonitorLocker ml(monitor_);
|
| + shutting_down_ = true;
|
| + }
|
| + SendServiceExitMessage();
|
| + {
|
| + MonitorLocker ml(monitor_);
|
| + while (shutting_down_ && (port_ != ILLEGAL_PORT)) {
|
| + ml.Wait();
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| Dart_Handle ServiceIsolate::GetSource(const char* name) {
|
| ASSERT(name != NULL);
|
| int i = 0;
|
|
|