Chromium Code Reviews| Index: runtime/vm/dart.cc |
| diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc |
| index a0f8584168dfbe011c6d4cb3eb835c5d8fb3d1f3..1638cc370b5ccd575f05c2bd435a1721ae85e073 100644 |
| --- a/runtime/vm/dart.cc |
| +++ b/runtime/vm/dart.cc |
| @@ -38,6 +38,7 @@ DECLARE_FLAG(bool, trace_isolates); |
| DECLARE_FLAG(bool, trace_time_all); |
| DEFINE_FLAG(bool, keep_code, false, |
| "Keep deoptimized code for profiling."); |
| +DEFINE_FLAG(bool, shutdown, true, "Do a clean shutdown of the VM"); |
| Isolate* Dart::vm_isolate_ = NULL; |
| ThreadPool* Dart::thread_pool_ = NULL; |
| @@ -196,38 +197,60 @@ const char* Dart::InitOnce(const uint8_t* vm_isolate_snapshot, |
| } |
| +// This waits until only the VM isolate remains in the list. |
| +void Dart::WaitForIsolateShutdown() { |
| + ASSERT(!Isolate::creation_enabled_); |
| + MonitorLocker ml(Isolate::isolates_list_monitor_); |
| + while ((Isolate::isolates_list_head_ != NULL) && |
| + (Isolate::isolates_list_head_->next_ != NULL)) { |
| + ml.Wait(); |
| + } |
| + ASSERT(Isolate::isolates_list_head_ == Dart::vm_isolate()); |
| +} |
| + |
| + |
| const char* Dart::Cleanup() { |
| - // Shutdown the service isolate before shutting down the thread pool. |
| - ServiceIsolate::Shutdown(); |
| -#if 0 |
| - // Ideally we should shutdown the VM isolate here, but the thread pool |
| - // shutdown does not seem to ensure that all the threads have stopped |
| - // execution before it terminates, this results in racing isolates. |
| + ASSERT(Isolate::Current() == NULL); |
| if (vm_isolate_ == NULL) { |
| return "VM already terminated."; |
| } |
| - ASSERT(Isolate::Current() == NULL); |
| + // Shut dwon profiling. |
|
turnidge
2015/09/15 16:48:22
dwon -> down
|
| + Profiler::Shutdown(); |
| - delete thread_pool_; |
| - thread_pool_ = NULL; |
| + if (FLAG_shutdown) { |
| + // Disable the creation of new isolates. |
| + Isolate::DisableIsolateCreation(); |
| - // Set the VM isolate as current isolate. |
| - Thread::EnsureInit(); |
| - Thread::EnterIsolate(vm_isolate_); |
| + // Send the OOB Kill message to all remaining application isolates. |
| + Isolate::KillAllIsolates(); |
| - // There is a planned and known asymmetry here: We exit one scope for the VM |
| - // isolate to account for the scope that was entered in Dart_InitOnce. |
| - Dart_ExitScope(); |
| + // Shutdown the service isolate. |
| + ServiceIsolate::Shutdown(); |
| - ShutdownIsolate(); |
| - vm_isolate_ = NULL; |
| + // Wait for all application isolates and the service isolate to shutdown |
| + // before shutting down the thread pool. |
| + WaitForIsolateShutdown(); |
| - TargetCPUFeatures::Cleanup(); |
| - StoreBuffer::ShutDown(); |
| -#endif |
| + // Shutdown the thread pool. On return, all thread pool threads have exited. |
| + delete thread_pool_; |
| + thread_pool_ = NULL; |
| + |
| + // Set the VM isolate as current isolate. |
| + Thread::EnsureInit(); |
| + Thread::EnterIsolate(vm_isolate_); |
| + |
| + ShutdownIsolate(); |
| + vm_isolate_ = NULL; |
| + ASSERT(Isolate::IsolateListLength() == 0); |
| + |
| + TargetCPUFeatures::Cleanup(); |
| + StoreBuffer::ShutDown(); |
| + } else { |
| + // Shutdown the service isolate. |
| + ServiceIsolate::Shutdown(); |
| + } |
| - Profiler::Shutdown(); |
| CodeObservers::DeleteAll(); |
| Timeline::Shutdown(); |
| Metric::Cleanup(); |