| Index: runtime/vm/dart.cc
|
| diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
|
| index e59c411f2c2f6a10e488c84b2879dbc13ad906f1..84350eb42d54102c7232140211e1cffa8b97f9fe 100644
|
| --- a/runtime/vm/dart.cc
|
| +++ b/runtime/vm/dart.cc
|
| @@ -37,6 +37,7 @@ DECLARE_FLAG(bool, print_class_table);
|
| DECLARE_FLAG(bool, trace_isolates);
|
| 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;
|
| @@ -195,38 +196,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.
|
| + 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();
|
|
|