summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/Android.common_test.mk7
-rw-r--r--build/Android.gtest.mk1
-rw-r--r--runtime/arch/arm64/instruction_set_features_arm64.cc1
-rw-r--r--runtime/class_linker.cc4
-rw-r--r--sigchainlib/Android.bp30
-rw-r--r--sigchainlib/sigchain.cc199
-rw-r--r--sigchainlib/sigchain_test.cc187
-rw-r--r--sigchainlib/version-script32.txt2
-rw-r--r--sigchainlib/version-script64.txt2
-rw-r--r--test/004-SignalTest/signaltest.cc18
-rw-r--r--test/115-native-bridge/expected.txt2
-rw-r--r--test/115-native-bridge/nativebridge.cc16
-rw-r--r--test/1926-missed-frame-pop/src/art/Test1926.java27
-rw-r--r--test/983-source-transform-verify/source_transform_slicer.cc7
-rw-r--r--test/ti-stress/stress.cc21
15 files changed, 433 insertions, 91 deletions
diff --git a/build/Android.common_test.mk b/build/Android.common_test.mk
index 7fae7f6200..c508fe7e9e 100644
--- a/build/Android.common_test.mk
+++ b/build/Android.common_test.mk
@@ -20,14 +20,11 @@ ART_ANDROID_COMMON_TEST_MK = true
include art/build/Android.common_path.mk
# Directory used for temporary test files on the host.
-ifneq ($(TMPDIR),)
-ART_HOST_TEST_DIR := $(TMPDIR)/test-art-$(shell echo $$PPID)
-else
# Use a BSD checksum calculated from CWD and USER as one of the path
# components for the test output. This should allow us to run tests from
# multiple repositories at the same time.
-ART_HOST_TEST_DIR := /tmp/test-art-$(shell echo $$CWD-${USER} | sum | cut -d ' ' -f1)
-endif
+ART_TMPDIR := $(if $(TMPDIR),$(TMPDIR),/tmp)
+ART_HOST_TEST_DIR := $(ART_TMPDIR)/test-art-$(shell echo $$CWD-${USER} | sum | cut -d ' ' -f1)
# List of known broken tests that we won't attempt to execute. The test name must be the full
# rule name such as test-art-host-oat-optimizing-HelloWorld64.
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 4a35ccfa13..388ff061a9 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -339,6 +339,7 @@ ART_TEST_MODULES := \
art_profman_tests \
art_runtime_tests \
art_runtime_compiler_tests \
+ art_sigchain_tests \
ART_TARGET_GTEST_FILES := $(foreach m,$(ART_TEST_MODULES),\
$(ART_TEST_LIST_device_$(TARGET_ARCH)_$(m)))
diff --git a/runtime/arch/arm64/instruction_set_features_arm64.cc b/runtime/arch/arm64/instruction_set_features_arm64.cc
index 9e9cb16008..42c9a846d0 100644
--- a/runtime/arch/arm64/instruction_set_features_arm64.cc
+++ b/runtime/arch/arm64/instruction_set_features_arm64.cc
@@ -54,6 +54,7 @@ Arm64FeaturesUniquePtr Arm64InstructionSetFeatures::FromVariant(
"cortex-a35",
"exynos-m1",
"exynos-m2",
+ "exynos-m3",
"denver64",
"kryo"
};
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 856e538ad6..f18e0b412c 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -267,7 +267,9 @@ static void WrapExceptionInInitializer(Handle<mirror::Class> klass)
// cannot in general be guaranteed, but in all likelihood leads to breakage down the line.
if (klass->GetClassLoader() == nullptr && !Runtime::Current()->IsAotCompiler()) {
std::string tmp;
- LOG(kIsDebugBuild ? FATAL : WARNING) << klass->GetDescriptor(&tmp) << " failed initialization";
+ LOG(kIsDebugBuild ? FATAL : WARNING) << klass->GetDescriptor(&tmp)
+ << " failed initialization: "
+ << self->GetException()->Dump();
}
env->ExceptionClear();
diff --git a/sigchainlib/Android.bp b/sigchainlib/Android.bp
index 7aab726be7..1f490cd3b9 100644
--- a/sigchainlib/Android.bp
+++ b/sigchainlib/Android.bp
@@ -16,15 +16,24 @@
cc_library {
name: "libsigchain",
+ cpp_std: "gnu++17",
+
host_supported: true,
defaults: ["art_defaults"],
- shared: {
- srcs: ["sigchain_dummy.cc"],
- },
- static: {
- srcs: ["sigchain.cc"],
- },
target: {
+ linux: {
+ shared: {
+ srcs: ["sigchain_dummy.cc"],
+ },
+ static: {
+ srcs: ["sigchain.cc"],
+ },
+ },
+
+ darwin: {
+ srcs: ["sigchain_dummy.cc"],
+ },
+
android: {
shared_libs: ["liblog"],
},
@@ -51,3 +60,12 @@ cc_library_static {
},
},
}
+
+art_cc_test {
+ name: "art_sigchain_tests",
+ defaults: [
+ "art_gtest_defaults",
+ ],
+ srcs: ["sigchain_test.cc"],
+ whole_static_libs: ["libsigchain"],
+}
diff --git a/sigchainlib/sigchain.cc b/sigchainlib/sigchain.cc
index b8ab51b629..61346b1487 100644
--- a/sigchainlib/sigchain.cc
+++ b/sigchainlib/sigchain.cc
@@ -29,8 +29,10 @@
#include <stdlib.h>
#include <string.h>
+#include <algorithm>
#include <initializer_list>
#include <mutex>
+#include <type_traits>
#include <utility>
#include "sigchain.h"
@@ -78,9 +80,28 @@ static void log(const char* format, ...) {
#define fatal(...) log(__VA_ARGS__); abort()
-static int sigorset(sigset_t* dest, sigset_t* left, sigset_t* right) {
+#if defined(__BIONIC__) && !defined(__LP64__)
+static int sigismember(const sigset64_t* sigset, int signum) {
+ return sigismember64(sigset, signum);
+}
+
+static int sigemptyset(sigset64_t* sigset) {
+ return sigemptyset64(sigset);
+}
+
+static int sigaddset(sigset64_t* sigset, int signum) {
+ return sigaddset64(sigset, signum);
+}
+
+static int sigdelset(sigset64_t* sigset, int signum) {
+ return sigdelset64(sigset, signum);
+}
+#endif
+
+template<typename SigsetType>
+static int sigorset(SigsetType* dest, SigsetType* left, SigsetType* right) {
sigemptyset(dest);
- for (size_t i = 0; i < sizeof(sigset_t) * CHAR_BIT; ++i) {
+ for (size_t i = 0; i < sizeof(SigsetType) * CHAR_BIT; ++i) {
if (sigismember(left, i) == 1 || sigismember(right, i) == 1) {
sigaddset(dest, i);
}
@@ -93,35 +114,36 @@ namespace art {
static decltype(&sigaction) linked_sigaction;
static decltype(&sigprocmask) linked_sigprocmask;
+#if defined(__BIONIC__)
+static decltype(&sigaction64) linked_sigaction64;
+static decltype(&sigprocmask64) linked_sigprocmask64;
+#endif
+
+template<typename T>
+static void lookup_next_symbol(T* output, T wrapper, const char* name) {
+ void* sym = dlsym(RTLD_NEXT, name);
+ if (sym == nullptr) {
+ sym = dlsym(RTLD_DEFAULT, name);
+ if (sym == wrapper || sym == sigaction) {
+ fatal("Unable to find next %s in signal chain", name);
+ }
+ }
+ *output = reinterpret_cast<T>(sym);
+}
+
__attribute__((constructor)) static void InitializeSignalChain() {
static std::once_flag once;
std::call_once(once, []() {
- void* linked_sigaction_sym = dlsym(RTLD_NEXT, "sigaction");
- if (linked_sigaction_sym == nullptr) {
- linked_sigaction_sym = dlsym(RTLD_DEFAULT, "sigaction");
- if (linked_sigaction_sym == nullptr ||
- linked_sigaction_sym == reinterpret_cast<void*>(sigaction)) {
- fatal("Unable to find next sigaction in signal chain");
- }
- }
-
- void* linked_sigprocmask_sym = dlsym(RTLD_NEXT, "sigprocmask");
- if (linked_sigprocmask_sym == nullptr) {
- linked_sigprocmask_sym = dlsym(RTLD_DEFAULT, "sigprocmask");
- if (linked_sigprocmask_sym == nullptr ||
- linked_sigprocmask_sym == reinterpret_cast<void*>(sigprocmask)) {
- fatal("Unable to find next sigprocmask in signal chain");
- }
- }
+ lookup_next_symbol(&linked_sigaction, sigaction, "sigaction");
+ lookup_next_symbol(&linked_sigprocmask, sigprocmask, "sigprocmask");
- linked_sigaction =
- reinterpret_cast<decltype(linked_sigaction)>(linked_sigaction_sym);
- linked_sigprocmask =
- reinterpret_cast<decltype(linked_sigprocmask)>(linked_sigprocmask_sym);
+#if defined(__BIONIC__)
+ lookup_next_symbol(&linked_sigaction64, sigaction64, "sigaction64");
+ lookup_next_symbol(&linked_sigprocmask64, sigprocmask64, "sigprocmask64");
+#endif
});
}
-
static pthread_key_t GetHandlingSignalKey() {
static pthread_key_t key;
static std::once_flag once;
@@ -175,19 +197,51 @@ class SignalChain {
// Register the signal chain with the kernel if needed.
void Register(int signo) {
+#if defined(__BIONIC__)
+ struct sigaction64 handler_action = {};
+ sigfillset64(&handler_action.sa_mask);
+#else
struct sigaction handler_action = {};
+ sigfillset(&handler_action.sa_mask);
+#endif
+
handler_action.sa_sigaction = SignalChain::Handler;
handler_action.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
- sigfillset(&handler_action.sa_mask);
+
+#if defined(__BIONIC__)
+ linked_sigaction64(signo, &handler_action, &action_);
+#else
linked_sigaction(signo, &handler_action, &action_);
+#endif
}
- void SetAction(const struct sigaction* action) {
- action_ = *action;
+ template <typename SigactionType>
+ SigactionType GetAction() {
+ if constexpr (std::is_same_v<decltype(action_), SigactionType>) {
+ return action_;
+ } else {
+ SigactionType result;
+ result.sa_flags = action_.sa_flags;
+ result.sa_handler = action_.sa_handler;
+ result.sa_restorer = action_.sa_restorer;
+ memcpy(&result.sa_mask, &action_.sa_mask,
+ std::min(sizeof(action_.sa_mask), sizeof(result.sa_mask)));
+ return result;
+ }
}
- struct sigaction GetAction() {
- return action_;
+ template <typename SigactionType>
+ void SetAction(const SigactionType* new_action) {
+ if constexpr (std::is_same_v<decltype(action_), SigactionType>) {
+ action_ = *new_action;
+ } else {
+ action_.sa_flags = new_action->sa_flags;
+ action_.sa_handler = new_action->sa_handler;
+ action_.sa_restorer = new_action->sa_restorer;
+ sigemptyset(&action_.sa_mask);
+ memcpy(&action_.sa_mask, &new_action->sa_mask,
+ std::min(sizeof(action_.sa_mask), sizeof(new_action->sa_mask)));
+ }
}
void AddSpecialHandler(SigchainAction* sa) {
@@ -222,11 +276,17 @@ class SignalChain {
private:
bool claimed_;
+#if defined(__BIONIC__)
+ struct sigaction64 action_;
+#else
struct sigaction action_;
+#endif
SigchainAction special_handlers_[2];
};
-static SignalChain chains[_NSIG];
+// _NSIG is 1 greater than the highest valued signal, but signals start from 1.
+// Leave an empty element at index 0 for convenience.
+static SignalChain chains[_NSIG + 1];
void SignalChain::Handler(int signo, siginfo_t* siginfo, void* ucontext_raw) {
// Try the special handlers first.
@@ -260,12 +320,22 @@ void SignalChain::Handler(int signo, siginfo_t* siginfo, void* ucontext_raw) {
// Forward to the user's signal handler.
int handler_flags = chains[signo].action_.sa_flags;
ucontext_t* ucontext = static_cast<ucontext_t*>(ucontext_raw);
+#if defined(__BIONIC__)
+ sigset64_t mask;
+ sigorset(&mask, &ucontext->uc_sigmask64, &chains[signo].action_.sa_mask);
+#else
sigset_t mask;
sigorset(&mask, &ucontext->uc_sigmask, &chains[signo].action_.sa_mask);
+#endif
if (!(handler_flags & SA_NODEFER)) {
sigaddset(&mask, signo);
}
+
+#if defined(__BIONIC__)
+ linked_sigprocmask64(SIG_SETMASK, &mask, nullptr);
+#else
linked_sigprocmask(SIG_SETMASK, &mask, nullptr);
+#endif
if ((handler_flags & SA_SIGINFO)) {
chains[signo].action_.sa_sigaction(signo, siginfo, ucontext_raw);
@@ -281,20 +351,22 @@ void SignalChain::Handler(int signo, siginfo_t* siginfo, void* ucontext_raw) {
}
}
-extern "C" int sigaction(int signal, const struct sigaction* new_action, struct sigaction* old_action) {
- InitializeSignalChain();
-
+template <typename SigactionType>
+static int __sigaction(int signal, const SigactionType* new_action,
+ SigactionType* old_action,
+ int (*linked)(int, const SigactionType*,
+ SigactionType*)) {
// If this signal has been claimed as a signal chain, record the user's
// action but don't pass it on to the kernel.
// Note that we check that the signal number is in range here. An out of range signal
// number should behave exactly as the libc sigaction.
- if (signal < 0 || signal >= _NSIG) {
+ if (signal <= 0 || signal >= _NSIG) {
errno = EINVAL;
return -1;
}
if (chains[signal].IsClaimed()) {
- struct sigaction saved_action = chains[signal].GetAction();
+ SigactionType saved_action = chains[signal].GetAction<SigactionType>();
if (new_action != nullptr) {
chains[signal].SetAction(new_action);
}
@@ -306,13 +378,27 @@ extern "C" int sigaction(int signal, const struct sigaction* new_action, struct
// Will only get here if the signal chain has not been claimed. We want
// to pass the sigaction on to the kernel via the real sigaction in libc.
- return linked_sigaction(signal, new_action, old_action);
+ return linked(signal, new_action, old_action);
+}
+
+extern "C" int sigaction(int signal, const struct sigaction* new_action,
+ struct sigaction* old_action) {
+ InitializeSignalChain();
+ return __sigaction(signal, new_action, old_action, linked_sigaction);
+}
+
+#if defined(__BIONIC__)
+extern "C" int sigaction64(int signal, const struct sigaction64* new_action,
+ struct sigaction64* old_action) {
+ InitializeSignalChain();
+ return __sigaction(signal, new_action, old_action, linked_sigaction64);
}
+#endif
extern "C" sighandler_t signal(int signo, sighandler_t handler) {
InitializeSignalChain();
- if (signo < 0 || signo > _NSIG) {
+ if (signo <= 0 || signo >= _NSIG) {
errno = EINVAL;
return SIG_ERR;
}
@@ -326,7 +412,8 @@ extern "C" sighandler_t signal(int signo, sighandler_t handler) {
// If this signal has been claimed as a signal chain, record the user's
// action but don't pass it on to the kernel.
if (chains[signo].IsClaimed()) {
- oldhandler = reinterpret_cast<sighandler_t>(chains[signo].GetAction().sa_handler);
+ oldhandler = reinterpret_cast<sighandler_t>(
+ chains[signo].GetAction<struct sigaction>().sa_handler);
chains[signo].SetAction(&sa);
return oldhandler;
}
@@ -348,23 +435,23 @@ extern "C" sighandler_t bsd_signal(int signo, sighandler_t handler) {
}
#endif
-extern "C" int sigprocmask(int how, const sigset_t* bionic_new_set, sigset_t* bionic_old_set) {
- InitializeSignalChain();
-
+template <typename SigsetType>
+int __sigprocmask(int how, const SigsetType* new_set, SigsetType* old_set,
+ int (*linked)(int, const SigsetType*, SigsetType*)) {
// When inside a signal handler, forward directly to the actual sigprocmask.
if (GetHandlingSignal()) {
- return linked_sigprocmask(how, bionic_new_set, bionic_old_set);
+ return linked(how, new_set, old_set);
}
- const sigset_t* new_set_ptr = bionic_new_set;
- sigset_t tmpset;
- if (bionic_new_set != nullptr) {
- tmpset = *bionic_new_set;
+ const SigsetType* new_set_ptr = new_set;
+ SigsetType tmpset;
+ if (new_set != nullptr) {
+ tmpset = *new_set;
- if (how == SIG_BLOCK) {
+ if (how == SIG_BLOCK || how == SIG_SETMASK) {
// Don't allow claimed signals in the mask. If a signal chain has been claimed
// we can't allow the user to block that signal.
- for (int i = 0 ; i < _NSIG; ++i) {
+ for (int i = 1; i < _NSIG; ++i) {
if (chains[i].IsClaimed() && sigismember(&tmpset, i)) {
sigdelset(&tmpset, i);
}
@@ -373,9 +460,23 @@ extern "C" int sigprocmask(int how, const sigset_t* bionic_new_set, sigset_t* bi
new_set_ptr = &tmpset;
}
- return linked_sigprocmask(how, new_set_ptr, bionic_old_set);
+ return linked(how, new_set_ptr, old_set);
}
+extern "C" int sigprocmask(int how, const sigset_t* new_set,
+ sigset_t* old_set) {
+ InitializeSignalChain();
+ return __sigprocmask(how, new_set, old_set, linked_sigprocmask);
+}
+
+#if defined(__BIONIC__)
+extern "C" int sigprocmask64(int how, const sigset64_t* new_set,
+ sigset64_t* old_set) {
+ InitializeSignalChain();
+ return __sigprocmask(how, new_set, old_set, linked_sigprocmask64);
+}
+#endif
+
extern "C" void AddSpecialSignalHandlerFn(int signal, SigchainAction* sa) {
InitializeSignalChain();
diff --git a/sigchainlib/sigchain_test.cc b/sigchainlib/sigchain_test.cc
new file mode 100644
index 0000000000..9f338ad3a2
--- /dev/null
+++ b/sigchainlib/sigchain_test.cc
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <signal.h>
+#include <sys/syscall.h>
+
+#include <functional>
+
+#include <gtest/gtest.h>
+
+#include "sigchain.h"
+
+#if !defined(__BIONIC__)
+typedef sigset_t sigset64_t;
+
+static int sigemptyset64(sigset64_t* set) {
+ return sigemptyset(set);
+}
+
+static int sigismember64(sigset64_t* set, int member) {
+ return sigismember(set, member);
+}
+#endif
+
+static int RealSigprocmask(int how, const sigset64_t* new_sigset, sigset64_t* old_sigset) {
+ // glibc's sigset_t is overly large, so sizeof(*new_sigset) doesn't work.
+ return syscall(__NR_rt_sigprocmask, how, new_sigset, old_sigset, 8);
+}
+
+class SigchainTest : public ::testing::Test {
+ void SetUp() final {
+ art::AddSpecialSignalHandlerFn(SIGSEGV, &action);
+ }
+
+ void TearDown() final {
+ art::RemoveSpecialSignalHandlerFn(SIGSEGV, action.sc_sigaction);
+ }
+
+ art::SigchainAction action = {
+ .sc_sigaction = [](int, siginfo_t*, void*) { return true; },
+ .sc_mask = {},
+ .sc_flags = 0,
+ };
+};
+
+
+static void TestSignalBlocking(std::function<void()> fn) {
+ // Unblock SIGSEGV, make sure it stays unblocked.
+ sigset64_t mask;
+ sigemptyset64(&mask);
+ ASSERT_EQ(0, RealSigprocmask(SIG_SETMASK, &mask, nullptr)) << strerror(errno);
+
+ fn();
+
+ if (testing::Test::HasFatalFailure()) return;
+ ASSERT_EQ(0, RealSigprocmask(SIG_SETMASK, nullptr, &mask));
+ ASSERT_FALSE(sigismember64(&mask, SIGSEGV));
+}
+
+TEST_F(SigchainTest, sigprocmask_setmask) {
+ TestSignalBlocking([]() {
+ sigset_t mask;
+ sigfillset(&mask);
+ ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &mask, nullptr));
+ });
+}
+
+TEST_F(SigchainTest, sigprocmask_block) {
+ TestSignalBlocking([]() {
+ sigset_t mask;
+ sigfillset(&mask);
+ ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &mask, nullptr));
+ });
+}
+
+// bionic-only wide variants for LP32.
+#if defined(__BIONIC__)
+TEST_F(SigchainTest, sigprocmask64_setmask) {
+ TestSignalBlocking([]() {
+ sigset64_t mask;
+ sigfillset64(&mask);
+ ASSERT_EQ(0, sigprocmask64(SIG_SETMASK, &mask, nullptr));
+ });
+}
+
+TEST_F(SigchainTest, sigprocmask64_block) {
+ TestSignalBlocking([]() {
+ sigset64_t mask;
+ sigfillset64(&mask);
+ ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &mask, nullptr));
+ });
+}
+
+TEST_F(SigchainTest, pthread_sigmask64_setmask) {
+ TestSignalBlocking([]() {
+ sigset64_t mask;
+ sigfillset64(&mask);
+ ASSERT_EQ(0, pthread_sigmask64(SIG_SETMASK, &mask, nullptr));
+ });
+}
+
+TEST_F(SigchainTest, pthread_sigmask64_block) {
+ TestSignalBlocking([]() {
+ sigset64_t mask;
+ sigfillset64(&mask);
+ ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, &mask, nullptr));
+ });
+}
+#endif
+
+// glibc doesn't implement most of these in terms of sigprocmask, which we rely on.
+#if defined(__BIONIC__)
+TEST_F(SigchainTest, pthread_sigmask_setmask) {
+ TestSignalBlocking([]() {
+ sigset_t mask;
+ sigfillset(&mask);
+ ASSERT_EQ(0, pthread_sigmask(SIG_SETMASK, &mask, nullptr));
+ });
+}
+
+TEST_F(SigchainTest, pthread_sigmask_block) {
+ TestSignalBlocking([]() {
+ sigset_t mask;
+ sigfillset(&mask);
+ ASSERT_EQ(0, pthread_sigmask(SIG_BLOCK, &mask, nullptr));
+ });
+}
+
+TEST_F(SigchainTest, sigset_mask) {
+ TestSignalBlocking([]() {
+ sigset(SIGSEGV, SIG_HOLD);
+ });
+}
+
+TEST_F(SigchainTest, sighold) {
+ TestSignalBlocking([]() {
+ sighold(SIGSEGV);
+ });
+}
+
+#if defined(__BIONIC__)
+// Not exposed via headers, but the symbols are available if you declare them yourself.
+extern "C" int sigblock(int);
+extern "C" int sigsetmask(int);
+#endif
+
+TEST_F(SigchainTest, sigblock) {
+ TestSignalBlocking([]() {
+ int mask = ~0U;
+ ASSERT_EQ(0, sigblock(mask));
+ });
+}
+
+TEST_F(SigchainTest, sigsetmask) {
+ TestSignalBlocking([]() {
+ int mask = ~0U;
+ ASSERT_EQ(0, sigsetmask(mask));
+ });
+}
+
+#endif
diff --git a/sigchainlib/version-script32.txt b/sigchainlib/version-script32.txt
index 2340785c42..e8a18e772c 100644
--- a/sigchainlib/version-script32.txt
+++ b/sigchainlib/version-script32.txt
@@ -5,8 +5,10 @@ global:
RemoveSpecialSignalHandlerFn;
bsd_signal;
sigaction;
+ sigaction64;
signal;
sigprocmask;
+ sigprocmask64;
local:
*;
};
diff --git a/sigchainlib/version-script64.txt b/sigchainlib/version-script64.txt
index acf36309ea..72c86a1ba8 100644
--- a/sigchainlib/version-script64.txt
+++ b/sigchainlib/version-script64.txt
@@ -4,8 +4,10 @@ global:
AddSpecialSignalHandlerFn;
RemoveSpecialSignalHandlerFn;
sigaction;
+ sigaction64;
signal;
sigprocmask;
+ sigprocmask64;
local:
*;
};
diff --git a/test/004-SignalTest/signaltest.cc b/test/004-SignalTest/signaltest.cc
index a58a0752c9..67118d5e63 100644
--- a/test/004-SignalTest/signaltest.cc
+++ b/test/004-SignalTest/signaltest.cc
@@ -99,6 +99,15 @@ static void signalhandler(int sig ATTRIBUTE_UNUSED, siginfo_t* info ATTRIBUTE_UN
static struct sigaction oldaction;
+bool compare_sigaction(const struct sigaction* lhs, const struct sigaction* rhs) {
+ // bionic's definition of `struct sigaction` has internal padding bytes, so we can't just do a
+ // naive memcmp of the entire struct.
+ return memcmp(&lhs->sa_mask, &rhs->sa_mask, sizeof(lhs->sa_mask)) == 0 &&
+ lhs->sa_sigaction == rhs->sa_sigaction &&
+ lhs->sa_flags == rhs->sa_flags &&
+ lhs->sa_restorer == rhs->sa_restorer;
+}
+
extern "C" JNIEXPORT void JNICALL Java_Main_initSignalTest(JNIEnv*, jclass) {
struct sigaction action;
action.sa_sigaction = signalhandler;
@@ -112,8 +121,15 @@ extern "C" JNIEXPORT void JNICALL Java_Main_initSignalTest(JNIEnv*, jclass) {
sigaction(SIGSEGV, &action, &oldaction);
struct sigaction check;
sigaction(SIGSEGV, nullptr, &check);
- if (memcmp(&action, &check, sizeof(action)) != 0) {
+ if (!compare_sigaction(&check, &action)) {
printf("sigaction returned different value\n");
+ printf("action.sa_mask = %p, check.sa_mask = %p\n",
+ *reinterpret_cast<void**>(&action.sa_mask),
+ *reinterpret_cast<void**>(&check.sa_mask));
+ printf("action.sa_sigaction = %p, check.sa_sigaction = %p\n",
+ action.sa_sigaction, check.sa_sigaction);
+ printf("action.sa_flags = %x, check.sa_flags = %x\n",
+ action.sa_flags, check.sa_flags);
}
signal(BLOCKED_SIGNAL, blocked_signal);
signal(UNBLOCKED_SIGNAL, unblocked_signal);
diff --git a/test/115-native-bridge/expected.txt b/test/115-native-bridge/expected.txt
index 343a76247e..06f5979f3e 100644
--- a/test/115-native-bridge/expected.txt
+++ b/test/115-native-bridge/expected.txt
@@ -63,6 +63,8 @@ trampoline_Java_Main_testNewStringObject called!
Getting trampoline for Java_Main_testSignal with shorty I.
NB signal handler with signal 11.
NB signal handler with signal 4.
+NB signal handler with signal 11.
+NB signal handler with signal 4.
Loading invalid library 'libinvalid.so' from Java, which will fail.
Checking for support.
Was to load 'libinvalid.so', force fail.
diff --git a/test/115-native-bridge/nativebridge.cc b/test/115-native-bridge/nativebridge.cc
index a049b97adc..3b352096df 100644
--- a/test/115-native-bridge/nativebridge.cc
+++ b/test/115-native-bridge/nativebridge.cc
@@ -224,6 +224,22 @@ static jint trampoline_Java_Main_testSignal(JNIEnv*, jclass) {
sigaction(SIGILL, &tmp, nullptr);
kill(getpid(), SIGILL);
+#if defined(__BIONIC__)
+ // Do the same again, but with sigaction64.
+ struct sigaction64 tmp2;
+ sigemptyset64(&tmp2.sa_mask);
+ tmp2.sa_sigaction = test_sigaction_handler;
+ tmp2.sa_restorer = nullptr;
+
+ sigaction64(SIGSEGV, &tmp2, nullptr);
+ sigaction64(SIGILL, &tmp2, nullptr);
+#endif
+
+ // Reraise SIGSEGV/SIGILL even on non-bionic, so that the expected output is
+ // the same.
+ raise_sigsegv();
+ kill(getpid(), SIGILL);
+
return 1234;
}
diff --git a/test/1926-missed-frame-pop/src/art/Test1926.java b/test/1926-missed-frame-pop/src/art/Test1926.java
index cb210729a9..1c6c33a9e6 100644
--- a/test/1926-missed-frame-pop/src/art/Test1926.java
+++ b/test/1926-missed-frame-pop/src/art/Test1926.java
@@ -166,17 +166,22 @@ public class Test1926 {
public static void doRecurTestWith(final int times, int watch_frame) throws Exception {
final String target_method_name_start = "recurTimes";
final ThreadPauser safepoint = new ThreadPauser();
- Thread target = new Thread(() -> {
- recurTimesA(times, () -> {
- safepoint.run();
- disableFramePop(null);
- });
- System.out.println("Ran recurTimes(" + times + ") without errors after disabling " +
- "frame pop event!");
- System.out.println("renabling frame pop event with similar stack.");
- recurTimesB(times, () -> { reenableFramePop(null); });
- System.out.println("Ran recurTimes(" + times + ") without errors!");
- });
+ // We need to make the stack bigger since ASAN causes SOE if we don't.
+ Thread target = new Thread(
+ /*thread Group*/ null,
+ () -> {
+ recurTimesA(times, () -> {
+ safepoint.run();
+ disableFramePop(null);
+ });
+ System.out.println("Ran recurTimes(" + times + ") without errors after disabling " +
+ "frame pop event!");
+ System.out.println("renabling frame pop event with similar stack.");
+ recurTimesB(times, () -> { reenableFramePop(null); });
+ System.out.println("Ran recurTimes(" + times + ") without errors!");
+ },
+ "Test1926-Thread",
+ /*10 mb stack*/10 * 1024 * 1024);
target.start();
safepoint.waitForOtherThreadToPause();
Suspension.suspend(target);
diff --git a/test/983-source-transform-verify/source_transform_slicer.cc b/test/983-source-transform-verify/source_transform_slicer.cc
index abf32e752e..34de625ed3 100644
--- a/test/983-source-transform-verify/source_transform_slicer.cc
+++ b/test/983-source-transform-verify/source_transform_slicer.cc
@@ -17,15 +17,10 @@
#include "source_transform.h"
#pragma clang diagnostic push
-// slicer defines its own CHECK. b/65422458
-#pragma push_macro("CHECK")
-#undef CHECK
-
// Slicer's headers have code that triggers these warnings. b/65298177
#pragma clang diagnostic ignored "-Wsign-compare"
-#include "reader.h"
+#include "slicer/reader.h"
-#pragma pop_macro("CHECK")
#pragma clang diagnostic pop
namespace art {
diff --git a/test/ti-stress/stress.cc b/test/ti-stress/stress.cc
index 7fc289faeb..d2da244397 100644
--- a/test/ti-stress/stress.cc
+++ b/test/ti-stress/stress.cc
@@ -29,22 +29,19 @@
#include "utils.h"
#pragma clang diagnostic push
-// slicer defines its own CHECK. b/65422458
-#pragma push_macro("CHECK")
-#undef CHECK
// Slicer's headers have code that triggers these warnings. b/65298177
#pragma clang diagnostic ignored "-Wunused-parameter"
#pragma clang diagnostic ignored "-Wsign-compare"
-#include "code_ir.h"
-#include "control_flow_graph.h"
-#include "dex_ir.h"
-#include "dex_ir_builder.h"
-#include "instrumentation.h"
-#include "reader.h"
-#include "writer.h"
-
-#pragma pop_macro("CHECK")
+
+#include "slicer/code_ir.h"
+#include "slicer/control_flow_graph.h"
+#include "slicer/dex_ir.h"
+#include "slicer/dex_ir_builder.h"
+#include "slicer/instrumentation.h"
+#include "slicer/reader.h"
+#include "slicer/writer.h"
+
#pragma clang diagnostic pop
namespace art {