Skip to content

Commit

Permalink
Introduce art::FastExit to replace all uses of quick_exit in ART.
Browse files Browse the repository at this point in the history
No longer use `quick_exit(3)` in ART, as it does not play well with
Clang's code coverage instrumentation (see b/187935521 and
b/186576313). Replace all its uses with a new routine,
`art::FastExit`, calling either `exit(3)` when ART is built with
Clang's code coverage instrumentation (in order to dump coverage
profiles when the program terminates) or `_exit(2)` otherwise (to exit
quickly).

Function `art::FastExit` is implemented as part of the
`art_libartbase_headers` header library, so that it can be used easily
in `dalvikvm`.

Test: mmma art
Test: ART tests
Bug: 186576313
Bug: 187935521
Change-Id: I7b4f86f6f0e7b12814684ecea73a2ed0ef994395
  • Loading branch information
roland-levillain committed May 27, 2021
1 parent f2d1a51 commit bdf1737
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 23 deletions.
3 changes: 3 additions & 0 deletions dalvikvm/Android.bp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ art_cc_binary {
"liblog",
"libnativehelper",
],
header_libs: [
"art_libartbase_headers", // For base/fast_exit.h
],
target: {
android: {
shared_libs: [
Expand Down
7 changes: 3 additions & 4 deletions dalvikvm/dalvikvm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <algorithm>
#include <memory>

#include "base/fast_exit.h"
#include "jni.h"
#include "nativehelper/JniInvocation.h"
#include "nativehelper/ScopedLocalRef.h"
Expand Down Expand Up @@ -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));
}
5 changes: 2 additions & 3 deletions dex2oat/dex2oat.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,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"
Expand Down Expand Up @@ -3157,11 +3158,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;
}
54 changes: 54 additions & 0 deletions libartbase/base/fast_exit.h
Original file line number Diff line number Diff line change
@@ -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_
8 changes: 3 additions & 5 deletions openjdkjvm/OpenjdkJvm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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"
Expand Down Expand Up @@ -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,
Expand Down
10 changes: 4 additions & 6 deletions perfetto_hprof/perfetto_hprof.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions runtime/runtime_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include <memory>

#include "base/fast_exit.h"
#include "base/sdk_version.h"
#include "base/utils.h"
#include "debugger.h"
Expand Down
8 changes: 3 additions & 5 deletions runtime/runtime_options.def
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit bdf1737

Please sign in to comment.