Use `quick_exit` instead of `_exit` (except for error handling).
Replace every occurrence of `_exit` (for cases other than pure error
handling) with `quick_exit`, in order to allow functions registered
with `at_quick_exit` to be called before exiting.
In particular, this change will allow LLVM's code coverage profile
dumping routine to be called before exiting ART processes.
Test: mmma art
Test: ART tests
Bug: 186576313
Change-Id: Ia9b0dbb471e2a26600c8bd23f7567931d050fc9d
diff --git a/dalvikvm/dalvikvm.cc b/dalvikvm/dalvikvm.cc
index 4808a1f..f2cc225 100644
--- a/dalvikvm/dalvikvm.cc
+++ b/dalvikvm/dalvikvm.cc
@@ -215,6 +215,8 @@
int main(int argc, char** argv) {
// Do not allow static destructors to be called, since it's conceivable that
- // daemons may still awaken (literally).
- _exit(art::dalvikvm(argc, argv));
+ // daemons may still awaken (literally); but still have functions registered
+ // with `at_quick_exit` (for instance LLVM's code coverage profile dumping
+ // routine) be called before exiting.
+ quick_exit(art::dalvikvm(argc, argv));
}
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 9de5ac5..042d671 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -3134,9 +3134,11 @@
int result = static_cast<int>(art::Dex2oat(argc, argv));
// Everything was done, do an explicit exit here to avoid running Runtime destructors that take
// time (bug 10645725) unless we're a debug or instrumented build or running on a memory tool.
+ // Also have functions registered with `at_quick_exit` (for instance LLVM's code coverage
+ // profile dumping routine) be called before exiting.
// Note: The Dex2Oat class should not destruct the runtime in this case.
if (!art::kIsDebugBuild && !art::kIsPGOInstrumentation && !art::kRunningOnMemoryTool) {
- _exit(result);
+ quick_exit(result);
}
return result;
}
diff --git a/openjdkjvm/OpenjdkJvm.cc b/openjdkjvm/OpenjdkJvm.cc
index 675a401..18078ab 100644
--- a/openjdkjvm/OpenjdkJvm.cc
+++ b/openjdkjvm/OpenjdkJvm.cc
@@ -35,6 +35,7 @@
#include <dlfcn.h>
#include <limits.h>
#include <stdio.h>
+#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
@@ -314,8 +315,10 @@
LOG(INFO) << "System.exit called, status: " << status;
art::Runtime::Current()->CallExitHook(status);
// Unsafe to call exit() while threads may still be running. They would race
- // with static destructors.
- _exit(status);
+ // with static destructors. However, have functions registered with
+ // `at_quick_exit` (for instance LLVM's code coverage profile dumping routine)
+ // be called before exiting.
+ quick_exit(status);
}
JNIEXPORT jstring JVM_NativeLoad(JNIEnv* env,
diff --git a/perfetto_hprof/perfetto_hprof.cc b/perfetto_hprof/perfetto_hprof.cc
index a27fc5c..c718cc0 100644
--- a/perfetto_hprof/perfetto_hprof.cc
+++ b/perfetto_hprof/perfetto_hprof.cc
@@ -23,6 +23,7 @@
#include <inttypes.h>
#include <sched.h>
#include <signal.h>
+#include <stdlib.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -913,8 +914,10 @@
LOG(INFO) << "finished dumping heap for " << parent_pid;
// Prevent the atexit handlers to run. We do not want to call cleanup
- // functions the parent process has registered.
- _exit(0);
+ // functions the parent process has registered. However, have functions
+ // registered with `at_quick_exit` (for instance LLVM's code coverage profile
+ // dumping routine) be called before exiting.
+ quick_exit(0);
}
// The plugin initialization function.
diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def
index e431183..ef5bed7 100644
--- a/runtime/runtime_options.def
+++ b/runtime/runtime_options.def
@@ -154,10 +154,12 @@
RUNTIME_OPTIONS_KEY (bool (*)(), HookIsSensitiveThread)
RUNTIME_OPTIONS_KEY (int32_t (*)(FILE* stream, const char* format, va_list ap), \
HookVfprintf, vfprintf)
-// Use _exit instead of exit so that we won't get DCHECK failures in global data
-// destructors. b/28106055.
+// Use `quick_exit` instead of `exit` so that we won't get DCHECK failures
+// in global data destructors (see b/28106055); but still have functions
+// registered with `at_quick_exit` (for instance LLVM's code coverage profile
+// dumping routine) be called before exiting.
RUNTIME_OPTIONS_KEY (void (*)(int32_t status), \
- HookExit, _exit)
+ HookExit, quick_exit)
// We don't call abort(3) by default; see
// Runtime::Abort.
RUNTIME_OPTIONS_KEY (void (*)(), HookAbort, nullptr)