diff options
-rw-r--r-- | dalvikvm/Android.bp | 3 | ||||
-rw-r--r-- | dalvikvm/dalvikvm.cc | 7 | ||||
-rw-r--r-- | dex2oat/dex2oat.cc | 5 | ||||
-rw-r--r-- | libartbase/base/fast_exit.h | 54 | ||||
-rw-r--r-- | openjdkjvm/OpenjdkJvm.cc | 8 | ||||
-rw-r--r-- | perfetto_hprof/perfetto_hprof.cc | 10 | ||||
-rw-r--r-- | runtime/runtime_options.cc | 1 | ||||
-rw-r--r-- | runtime/runtime_options.def | 8 |
8 files changed, 73 insertions, 23 deletions
diff --git a/dalvikvm/Android.bp b/dalvikvm/Android.bp index a1f57ca5c7..6e06eba52a 100644 --- a/dalvikvm/Android.bp +++ b/dalvikvm/Android.bp @@ -34,6 +34,9 @@ art_cc_binary { "liblog", "libnativehelper", ], + header_libs: [ + "art_libartbase_headers", // For base/fast_exit.h + ], target: { android: { shared_libs: [ diff --git a/dalvikvm/dalvikvm.cc b/dalvikvm/dalvikvm.cc index f2cc225e8b..27709fda4a 100644 --- a/dalvikvm/dalvikvm.cc +++ b/dalvikvm/dalvikvm.cc @@ -21,6 +21,7 @@ #include <algorithm> #include <memory> +#include "base/fast_exit.h" #include "jni.h" #include "nativehelper/JniInvocation.h" #include "nativehelper/ScopedLocalRef.h" @@ -215,8 +216,6 @@ extern "C" const char *__asan_default_options() { int main(int argc, char** argv) { // Do not allow static destructors to be called, since it's conceivable that - // 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)); + // daemons may still awaken (literally). + art::FastExit(art::dalvikvm(argc, argv)); } diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index c613e33336..fa1a10e4fd 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -53,6 +53,7 @@ #include "base/macros.h" #include "base/mutex.h" #include "base/os.h" +#include "base/fast_exit.h" #include "base/scoped_flock.h" #include "base/stl_util.h" #include "base/time_utils.h" @@ -3142,11 +3143,9 @@ int main(int argc, char** argv) { 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) { - quick_exit(result); + art::FastExit(result); } return result; } diff --git a/libartbase/base/fast_exit.h b/libartbase/base/fast_exit.h new file mode 100644 index 0000000000..35dd85e7e1 --- /dev/null +++ b/libartbase/base/fast_exit.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_LIBARTBASE_BASE_FAST_EXIT_H_ +#define ART_LIBARTBASE_BASE_FAST_EXIT_H_ + +// Header-only definition of `art::FastExit`. +// +// Ideally, this routine should be declared in `base/os.h` and defined in +// `base/os_linux.cc`, but as `libartbase` is not linked (directly) with +// `dalvikvm`, we would not be able to easily use `art::FastExit` in +// `dex2oat`. Use a header-only approach and define `art::FastExit` in its own +// file for clarity. + +#include <base/macros.h> + +namespace art { + +#ifdef __ANDROID_CLANG_COVERAGE__ +static constexpr bool kAndroidClangCoverage = true; +#else +static constexpr bool kAndroidClangCoverage = false; +#endif + +// Terminate program without completely cleaning the resources (e.g. without +// calling destructors), unless ART is built with Clang (native) code coverage +// instrumentation; in that case, exit normally to allow LLVM's code coverage +// profile dumping routine (`__llvm_profile_write_file`), registered via +// `atexit` in Android when Clang instrumentation is enabled, to be called +// before terminating the program. +NO_RETURN inline void FastExit(int exit_code) { + if (kAndroidClangCoverage) { + exit(exit_code); + } else { + _exit(exit_code); + } +} + +} // namespace art + +#endif // ART_LIBARTBASE_BASE_FAST_EXIT_H_ diff --git a/openjdkjvm/OpenjdkJvm.cc b/openjdkjvm/OpenjdkJvm.cc index 18078abdad..d64086d43c 100644 --- a/openjdkjvm/OpenjdkJvm.cc +++ b/openjdkjvm/OpenjdkJvm.cc @@ -35,7 +35,6 @@ #include <dlfcn.h> #include <limits.h> #include <stdio.h> -#include <stdlib.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <sys/time.h> @@ -46,6 +45,7 @@ #include "../../libcore/ojluni/src/main/native/jvm.h" // TODO(narayan): fix it #include "base/macros.h" +#include "base/fast_exit.h" #include "common_throws.h" #include "gc/heap.h" #include "handle_scope-inl.h" @@ -315,10 +315,8 @@ JNIEXPORT __attribute__((noreturn)) void JVM_Exit(jint status) { 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. However, have functions registered with - // `at_quick_exit` (for instance LLVM's code coverage profile dumping routine) - // be called before exiting. - quick_exit(status); + // with static destructors. + art::FastExit(status); } JNIEXPORT jstring JVM_NativeLoad(JNIEnv* env, diff --git a/perfetto_hprof/perfetto_hprof.cc b/perfetto_hprof/perfetto_hprof.cc index 0a7f38072b..3affe8d232 100644 --- a/perfetto_hprof/perfetto_hprof.cc +++ b/perfetto_hprof/perfetto_hprof.cc @@ -19,11 +19,11 @@ #include "perfetto_hprof.h" #include <android-base/logging.h> +#include <base/fast_exit.h> #include <fcntl.h> #include <inttypes.h> #include <sched.h> #include <signal.h> -#include <stdlib.h> #include <sys/socket.h> #include <sys/stat.h> #include <sys/types.h> @@ -847,11 +847,9 @@ void DumpPerfetto(art::Thread* self) { }); 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. However, have functions - // registered with `at_quick_exit` (for instance LLVM's code coverage profile - // dumping routine) be called before exiting. - quick_exit(0); + // Prevent the `atexit` handlers from running. We do not want to call cleanup + // functions the parent process has registered. + art::FastExit(0); } // The plugin initialization function. diff --git a/runtime/runtime_options.cc b/runtime/runtime_options.cc index 12dab158e5..e21587ad1b 100644 --- a/runtime/runtime_options.cc +++ b/runtime/runtime_options.cc @@ -18,6 +18,7 @@ #include <memory> +#include "base/fast_exit.h" #include "base/sdk_version.h" #include "base/utils.h" #include "debugger.h" diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def index 3f0e3cca59..3743670f46 100644 --- a/runtime/runtime_options.def +++ b/runtime/runtime_options.def @@ -156,12 +156,10 @@ RUNTIME_OPTIONS_KEY (CompilerCallbacks*, CompilerCallbacksPtr) // TODO: make u RUNTIME_OPTIONS_KEY (bool (*)(), HookIsSensitiveThread) RUNTIME_OPTIONS_KEY (int32_t (*)(FILE* stream, const char* format, va_list ap), \ HookVfprintf, vfprintf) -// 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. +// Use `art::FastExit` instead of `exit` so that we won't get DCHECK failures +// in global data destructors (see b/28106055). RUNTIME_OPTIONS_KEY (void (*)(int32_t status), \ - HookExit, quick_exit) + HookExit, art::FastExit) // We don't call abort(3) by default; see // Runtime::Abort. RUNTIME_OPTIONS_KEY (void (*)(), HookAbort, nullptr) |