base: add quick_exit emulation.
Bug: http://b/31468413 Change-Id: Ie15fcb8ff0613d01a0eb7437a2cb37283aa52bab Test: mma, libbase_test on Linux/Windows
This commit is contained in:
parent
63bdcb57aa
commit
0c44256ae4
4 changed files with 138 additions and 0 deletions
|
@ -28,6 +28,7 @@ cc_library {
|
|||
"file.cpp",
|
||||
"logging.cpp",
|
||||
"parsenetaddress.cpp",
|
||||
"quick_exit.cpp",
|
||||
"stringprintf.cpp",
|
||||
"strings.cpp",
|
||||
"test_utils.cpp",
|
||||
|
@ -71,6 +72,7 @@ cc_test {
|
|||
"logging_test.cpp",
|
||||
"parseint_test.cpp",
|
||||
"parsenetaddress_test.cpp",
|
||||
"quick_exit_test.cpp",
|
||||
"stringprintf_test.cpp",
|
||||
"strings_test.cpp",
|
||||
"test_main.cpp",
|
||||
|
|
34
base/include/android-base/quick_exit.h
Normal file
34
base/include/android-base/quick_exit.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
// Provide emulation for at_quick_exit/quick_exit on platforms that don't have it.
|
||||
namespace android {
|
||||
namespace base {
|
||||
|
||||
// Bionic and glibc have quick_exit, Darwin and Windows don't.
|
||||
#if !defined(__linux__)
|
||||
void quick_exit(int exit_code) __attribute__((noreturn));
|
||||
int at_quick_exit(void (*func)());
|
||||
#else
|
||||
using ::at_quick_exit;
|
||||
using ::quick_exit;
|
||||
#endif
|
||||
}
|
||||
}
|
48
base/quick_exit.cpp
Normal file
48
base/quick_exit.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
#include "android-base/quick_exit.h"
|
||||
|
||||
#if !defined(__linux__)
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include "android-base/mutex.h"
|
||||
|
||||
namespace android {
|
||||
namespace base {
|
||||
|
||||
static std::mutex quick_exit_mutex;
|
||||
static std::vector<void(*)()> quick_exit_handlers;
|
||||
|
||||
void quick_exit(int exit_code) {
|
||||
std::lock_guard<std::mutex> lock(quick_exit_mutex);
|
||||
for (auto it = quick_exit_handlers.rbegin(); it != quick_exit_handlers.rend(); ++it) {
|
||||
(*it)();
|
||||
}
|
||||
_Exit(exit_code);
|
||||
}
|
||||
|
||||
int at_quick_exit(void (*func)()) {
|
||||
std::lock_guard<std::mutex> lock(quick_exit_mutex);
|
||||
quick_exit_handlers.push_back(func);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
} // namespace android
|
||||
#endif
|
54
base/quick_exit_test.cpp
Normal file
54
base/quick_exit_test.cpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
#include "android-base/quick_exit.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "android-base/test_utils.h"
|
||||
|
||||
// These tests are a bit sketchy, since each test run adds global state that affects subsequent
|
||||
// tests (including ones not in this file!). Exit with 0 in Exiter and stick the at_quick_exit test
|
||||
// at the end to hack around this.
|
||||
struct Exiter {
|
||||
~Exiter() {
|
||||
_Exit(0);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(quick_exit, smoke) {
|
||||
ASSERT_EXIT(android::base::quick_exit(123), testing::ExitedWithCode(123), "");
|
||||
}
|
||||
|
||||
TEST(quick_exit, skip_static_destructors) {
|
||||
static Exiter exiter;
|
||||
ASSERT_EXIT(android::base::quick_exit(123), testing::ExitedWithCode(123), "");
|
||||
}
|
||||
|
||||
TEST(quick_exit, at_quick_exit) {
|
||||
static int counter = 4;
|
||||
// "Functions passed to at_quick_exit are called in reverse order of their registration."
|
||||
ASSERT_EQ(0, android::base::at_quick_exit([]() { _exit(counter); }));
|
||||
ASSERT_EQ(0, android::base::at_quick_exit([]() { counter += 2; }));
|
||||
ASSERT_EQ(0, android::base::at_quick_exit([]() { counter *= 10; }));
|
||||
ASSERT_EXIT(android::base::quick_exit(123), testing::ExitedWithCode(42), "");
|
||||
}
|
Loading…
Reference in a new issue