diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc index 92e08ac3802..eae320d6551 100644 --- a/runtime/bin/main.cc +++ b/runtime/bin/main.cc @@ -630,6 +630,8 @@ static int ErrorExit(int exit_code, const char* format, ...) { Dart_ExitScope(); Dart_ShutdownIsolate(); + Dart_Cleanup(); + return exit_code; } @@ -799,8 +801,6 @@ int main(int argc, char** argv) { result = Dart_CreateScriptSnapshot(&buffer, &size); if (Dart_IsError(result)) { Log::PrintErr("%s\n", Dart_GetError(result)); - Dart_ExitScope(); - Dart_ShutdownIsolate(); return DartErrorExit(result); } @@ -875,6 +875,8 @@ int main(int argc, char** argv) { // Terminate process exit-code handler. Process::TerminateExitCodeHandler(); + Dart_Cleanup(); + // Free copied argument strings if converted. if (argv_converted) { for (int i = 0; i < argc; i++) free(argv[i]); diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h index 9f4969e16f5..93659f6046c 100755 --- a/runtime/include/dart_api.h +++ b/runtime/include/dart_api.h @@ -749,6 +749,13 @@ DART_EXPORT bool Dart_Initialize( Dart_FileWriteCallback file_write, Dart_FileCloseCallback file_close); +/** + * Cleanup state in the VM before process termination. + * + * \return True if cleanup is successful. + */ +DART_EXPORT bool Dart_Cleanup(); + /** * Sets command line flags. Should be called before Dart_Initialize. * diff --git a/runtime/vm/code_observers.cc b/runtime/vm/code_observers.cc index 1e8835a7134..487337136c1 100644 --- a/runtime/vm/code_observers.cc +++ b/runtime/vm/code_observers.cc @@ -50,6 +50,8 @@ void CodeObservers::DeleteAll() { delete observers_[i]; } free(observers_); + observers_length_ = 0; + observers_ = NULL; } diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc index af17f5e4c7e..e81438f82ce 100644 --- a/runtime/vm/dart.cc +++ b/runtime/vm/dart.cc @@ -74,7 +74,6 @@ class ReadOnlyHandles { }; -// TODO(turnidge): We should add a corresponding Dart::Cleanup. const char* Dart::InitOnce(Dart_IsolateCreateCallback create, Dart_IsolateInterruptCallback interrupt, Dart_IsolateUnhandledExceptionCallback unhandled, @@ -144,6 +143,37 @@ const char* Dart::InitOnce(Dart_IsolateCreateCallback create, } +const char* Dart::Cleanup() { +#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. + if (vm_isolate_ == NULL) { + return "VM already terminated."; + } + + ASSERT(Isolate::Current() == NULL); + + delete thread_pool_; + thread_pool_ = NULL; + + // Set the VM isolate as current isolate. + Isolate::SetCurrent(vm_isolate_); + + // 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(); + + ShutdownIsolate(); + vm_isolate_ = NULL; +#endif + + CodeObservers::DeleteAll(); + + return NULL; +} + + Isolate* Dart::CreateIsolate(const char* name_prefix) { // Create a new isolate. Isolate* isolate = Isolate::Init(name_prefix); diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h index d1c592a6ed7..edb18adf44c 100644 --- a/runtime/vm/dart.h +++ b/runtime/vm/dart.h @@ -28,6 +28,7 @@ class Dart : public AllStatic { Dart_FileReadCallback file_read, Dart_FileWriteCallback file_write, Dart_FileCloseCallback file_close); + static const char* Cleanup(); static Isolate* CreateIsolate(const char* name_prefix); static RawError* InitializeIsolate(const uint8_t* snapshot, void* data); diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc index 680476e5435..fc71298a904 100644 --- a/runtime/vm/dart_api_impl.cc +++ b/runtime/vm/dart_api_impl.cc @@ -761,10 +761,23 @@ DART_EXPORT bool Dart_Initialize( return true; } + +DART_EXPORT bool Dart_Cleanup() { + CHECK_NO_ISOLATE(Isolate::Current()); + const char* err_msg = Dart::Cleanup(); + if (err_msg != NULL) { + OS::PrintErr("Dart_Cleanup: %s\n", err_msg); + return false; + } + return true; +} + + DART_EXPORT bool Dart_SetVMFlags(int argc, const char** argv) { return Flags::ProcessCommandLineFlags(argc, argv); } + DART_EXPORT bool Dart_IsVMFlagSet(const char* flag_name) { if (Flags::Lookup(flag_name) != NULL) { return true; diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc index 0e6ad033706..d8ab9a53852 100644 --- a/runtime/vm/isolate.cc +++ b/runtime/vm/isolate.cc @@ -680,9 +680,6 @@ void Isolate::Shutdown() { api_state()->weak_persistent_handles().VisitHandles(&visitor); CompilerStats::Print(); - // TODO(asiva): Move this code to Dart::Cleanup when we have that method - // as the cleanup for Dart::InitOnce. - CodeObservers::DeleteAll(); if (FLAG_trace_isolates) { heap()->PrintSizes(); megamorphic_cache_table()->PrintSizes();