Add `sigset64_t` and accompanying functions.
This doesn't address `struct sigaction` and `sigaction`. That will
come later.
Bug: http://b/72493232
Test: ran tests
Change-Id: I4134346757ce3a4dac6feae413361cec16223386
diff --git a/tests/Android.bp b/tests/Android.bp
index 25377df..443fe8e 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -140,6 +140,7 @@
"sys_sem_test.cpp",
"sys_sendfile_test.cpp",
"sys_shm_test.cpp",
+ "sys_signalfd_test.cpp",
"sys_socket_test.cpp",
"sys_stat_test.cpp",
"sys_statvfs_test.cpp",
diff --git a/tests/ScopedSignalHandler.h b/tests/ScopedSignalHandler.h
index 71f22dc..85c41a8 100644
--- a/tests/ScopedSignalHandler.h
+++ b/tests/ScopedSignalHandler.h
@@ -20,6 +20,26 @@
#include <signal.h>
#include <string.h>
+#if defined(__GLIBC__)
+#define posix_spawnattr_getsigdefault64 posix_spawnattr_getsigdefault
+#define posix_spawnattr_getsigmask64 posix_spawnattr_getsigmask
+#define posix_spawnattr_setsigdefault64 posix_spawnattr_setsigdefault
+#define posix_spawnattr_setsigmask64 posix_spawnattr_setsigmask
+#define pthread_sigmask64 pthread_sigmask
+#define sigaddset64 sigaddset
+#define sigdelset64 sigdelset
+#define sigemptyset64 sigemptyset
+#define sigfillset64 sigfillset
+#define sigismember64 sigismember
+#define sigpending64 sigpending
+#define sigprocmask64 sigprocmask
+#define sigset64_t sigset_t
+#define sigsuspend64 sigsuspend
+#define sigtimedwait64 sigtimedwait
+#define sigwait64 sigwait
+#define sigwaitinfo64 sigwaitinfo
+#endif
+
class ScopedSignalHandler {
public:
ScopedSignalHandler(int signal_number, void (*handler)(int), int sa_flags = 0)
@@ -56,15 +76,15 @@
class SignalMaskRestorer {
public:
SignalMaskRestorer() {
- sigprocmask(SIG_SETMASK, nullptr, &old_mask_);
+ sigprocmask64(SIG_SETMASK, nullptr, &old_mask_);
}
~SignalMaskRestorer() {
- sigprocmask(SIG_SETMASK, &old_mask_, nullptr);
+ sigprocmask64(SIG_SETMASK, &old_mask_, nullptr);
}
private:
- sigset_t old_mask_;
+ sigset64_t old_mask_;
};
#endif // _BIONIC_TESTS_SCOPED_SIGNAL_HANDLER_H
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 9ecb10c..f812df5 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -356,9 +356,9 @@
}
static void* SignalHandlerFn(void* arg) {
- sigset_t wait_set;
- sigfillset(&wait_set);
- return reinterpret_cast<void*>(sigwait(&wait_set, reinterpret_cast<int*>(arg)));
+ sigset64_t wait_set;
+ sigfillset64(&wait_set);
+ return reinterpret_cast<void*>(sigwait64(&wait_set, reinterpret_cast<int*>(arg)));
}
TEST(pthread, pthread_sigmask) {
@@ -402,6 +402,47 @@
ASSERT_EQ(0, pthread_sigmask(SIG_SETMASK, &original_set, NULL));
}
+TEST(pthread, pthread_sigmask64_SIGTRMIN) {
+ // Check that SIGRTMIN isn't blocked.
+ sigset64_t original_set;
+ sigemptyset64(&original_set);
+ ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, NULL, &original_set));
+ ASSERT_FALSE(sigismember64(&original_set, SIGRTMIN));
+
+ // Block SIGRTMIN.
+ sigset64_t set;
+ sigemptyset64(&set);
+ sigaddset64(&set, SIGRTMIN);
+ ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, &set, NULL));
+
+ // Check that SIGRTMIN is blocked.
+ sigset64_t final_set;
+ sigemptyset64(&final_set);
+ ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, NULL, &final_set));
+ ASSERT_TRUE(sigismember64(&final_set, SIGRTMIN));
+ // ...and that sigprocmask64 agrees with pthread_sigmask64.
+ sigemptyset64(&final_set);
+ ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, NULL, &final_set));
+ ASSERT_TRUE(sigismember64(&final_set, SIGRTMIN));
+
+ // Spawn a thread that calls sigwait64 and tells us what it received.
+ pthread_t signal_thread;
+ int received_signal = -1;
+ ASSERT_EQ(0, pthread_create(&signal_thread, NULL, SignalHandlerFn, &received_signal));
+
+ // Send that thread SIGRTMIN.
+ pthread_kill(signal_thread, SIGRTMIN);
+
+ // See what it got.
+ void* join_result;
+ ASSERT_EQ(0, pthread_join(signal_thread, &join_result));
+ ASSERT_EQ(SIGRTMIN, received_signal);
+ ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(join_result));
+
+ // Restore the original signal mask.
+ ASSERT_EQ(0, pthread_sigmask64(SIG_SETMASK, &original_set, NULL));
+}
+
static void test_pthread_setname_np__pthread_getname_np(pthread_t t) {
ASSERT_EQ(0, pthread_setname_np(t, "short"));
char name[32];
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index 5cbec88..ebc079e 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -20,57 +20,45 @@
#include <sys/types.h>
#include <unistd.h>
+#include <thread>
+
#include <gtest/gtest.h>
#include "ScopedSignalHandler.h"
-static size_t SIGNAL_MIN() {
+static int SIGNAL_MIN() {
return 1; // Signals start at 1 (SIGHUP), not 0.
}
-static size_t SIGNAL_MAX() {
- size_t result = SIGRTMAX;
-
-#if defined(__BIONIC__) && !defined(__mips__) && !defined(__LP64__)
- // 32-bit bionic's sigset_t is too small for ARM and x86: 32 bits instead of 64.
- // This means you can't refer to any of the real-time signals.
- // See http://b/3038348 and http://b/5828899.
- result = 32;
-#else
- // Otherwise, C libraries should be perfectly capable of using their largest signal.
- if (sizeof(sigset_t) * 8 < static_cast<size_t>(SIGRTMAX)) {
- abort();
- }
-#endif
-
- return result;
+template <typename SigSetT>
+static int SIGNAL_MAX(SigSetT* set) {
+ return sizeof(*set) * 8;
}
-template <typename Fn>
-static void TestSigSet1(Fn fn) {
- // NULL sigset_t*.
- sigset_t* set_ptr = NULL;
+template <typename SigSetT>
+static void TestSigSet1(int (fn)(SigSetT*)) {
+ // NULL sigset_t*/sigset64_t*.
+ SigSetT* set_ptr = NULL;
errno = 0;
ASSERT_EQ(-1, fn(set_ptr));
ASSERT_EQ(EINVAL, errno);
// Non-NULL.
- sigset_t set;
+ SigSetT set = {};
errno = 0;
ASSERT_EQ(0, fn(&set));
ASSERT_EQ(0, errno);
}
-template <typename Fn>
-static void TestSigSet2(Fn fn) {
- // NULL sigset_t*.
- sigset_t* set_ptr = NULL;
+template <typename SigSetT>
+static void TestSigSet2(int (fn)(SigSetT*, int)) {
+ // NULL sigset_t*/sigset64_t*.
+ SigSetT* set_ptr = NULL;
errno = 0;
ASSERT_EQ(-1, fn(set_ptr, SIGSEGV));
ASSERT_EQ(EINVAL, errno);
- sigset_t set;
- sigemptyset(&set);
+ SigSetT set = {};
// Bad signal number: too small.
errno = 0;
@@ -79,37 +67,67 @@
// Bad signal number: too high.
errno = 0;
- ASSERT_EQ(-1, fn(&set, SIGNAL_MAX() + 1));
+ ASSERT_EQ(-1, fn(&set, SIGNAL_MAX(&set) + 1));
ASSERT_EQ(EINVAL, errno);
// Good signal numbers, low and high ends of range.
errno = 0;
ASSERT_EQ(0, fn(&set, SIGNAL_MIN()));
ASSERT_EQ(0, errno);
- ASSERT_EQ(0, fn(&set, SIGNAL_MAX()));
+ ASSERT_EQ(0, fn(&set, SIGNAL_MAX(&set)));
ASSERT_EQ(0, errno);
}
-TEST(signal, sigismember_invalid) {
- TestSigSet2(sigismember);
-}
-
TEST(signal, sigaddset_invalid) {
TestSigSet2(sigaddset);
}
+TEST(signal, sigaddset64_invalid) {
+#if defined(__BIONIC__)
+ TestSigSet2(sigaddset64);
+#endif
+}
+
TEST(signal, sigdelset_invalid) {
TestSigSet2(sigdelset);
}
+TEST(signal, sigdelset64_invalid) {
+#if defined(__BIONIC__)
+ TestSigSet2(sigdelset64);
+#endif
+}
+
TEST(signal, sigemptyset_invalid) {
TestSigSet1(sigemptyset);
}
+TEST(signal, sigemptyset64_invalid) {
+#if defined(__BIONIC__)
+ TestSigSet1(sigemptyset64);
+#endif
+}
+
TEST(signal, sigfillset_invalid) {
TestSigSet1(sigfillset);
}
+TEST(signal, sigfillset64_invalid) {
+#if defined(__BIONIC__)
+ TestSigSet1(sigfillset64);
+#endif
+}
+
+TEST(signal, sigismember_invalid) {
+ TestSigSet2(sigismember);
+}
+
+TEST(signal, sigismember64_invalid) {
+#if defined(__BIONIC__)
+ TestSigSet2(sigismember64);
+#endif
+}
+
TEST(signal, raise_invalid) {
errno = 0;
ASSERT_EQ(-1, raise(-1));
@@ -129,12 +147,8 @@
raise(SIGALRM);
}
-static void HandleSIGALRM(int signal_number) {
- ASSERT_EQ(SIGALRM, signal_number);
-}
-
-TEST(signal, sigwait) {
- ScopedSignalHandler ssh(SIGALRM, HandleSIGALRM);
+TEST(signal, sigwait_SIGALRM) {
+ ScopedSignalHandler ssh(SIGALRM, [](int sig) { ASSERT_EQ(SIGALRM, sig); });
sigset_t wait_set;
sigemptyset(&wait_set);
@@ -149,38 +163,57 @@
ASSERT_EQ(SIGALRM, received_signal);
}
-static int g_sigsuspend_test_helper_call_count = 0;
+TEST(signal, sigwait64_SIGRTMIN) {
+ ScopedSignalHandler ssh(SIGRTMIN, [](int sig) { ASSERT_EQ(SIGRTMIN, sig); });
-static void SigSuspendTestHelper(int) {
- ++g_sigsuspend_test_helper_call_count;
+ sigset64_t wait_set;
+ sigemptyset64(&wait_set);
+ sigaddset64(&wait_set, SIGRTMIN);
+
+ pid_t pid = getpid();
+ std::thread thread([&pid]() {
+ usleep(5000);
+ kill(pid, SIGRTMIN);
+ });
+
+ int received_signal;
+ errno = 0;
+ ASSERT_EQ(0, sigwait64(&wait_set, &received_signal));
+ ASSERT_EQ(0, errno);
+ ASSERT_EQ(SIGRTMIN, received_signal);
+
+ thread.join();
}
+static int g_sigsuspend_signal_handler_call_count = 0;
+
TEST(signal, sigsuspend_sigpending) {
+ SignalMaskRestorer smr;
+
// Block SIGALRM.
sigset_t just_SIGALRM;
sigemptyset(&just_SIGALRM);
sigaddset(&just_SIGALRM, SIGALRM);
- sigset_t original_set;
- ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set));
+ ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr));
- ScopedSignalHandler ssh(SIGALRM, SigSuspendTestHelper);
+ ScopedSignalHandler ssh(SIGALRM, [](int) { ++g_sigsuspend_signal_handler_call_count; });
// There should be no pending signals.
sigset_t pending;
sigemptyset(&pending);
ASSERT_EQ(0, sigpending(&pending));
- for (size_t i = SIGNAL_MIN(); i <= SIGNAL_MAX(); ++i) {
+ for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) {
EXPECT_FALSE(sigismember(&pending, i)) << i;
}
// Raise SIGALRM and check our signal handler wasn't called.
raise(SIGALRM);
- ASSERT_EQ(0, g_sigsuspend_test_helper_call_count);
+ ASSERT_EQ(0, g_sigsuspend_signal_handler_call_count);
// We should now have a pending SIGALRM but nothing else.
sigemptyset(&pending);
ASSERT_EQ(0, sigpending(&pending));
- for (size_t i = SIGNAL_MIN(); i <= SIGNAL_MAX(); ++i) {
+ for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) {
EXPECT_EQ((i == SIGALRM), sigismember(&pending, i));
}
@@ -191,10 +224,49 @@
ASSERT_EQ(-1, sigsuspend(¬_SIGALRM));
ASSERT_EQ(EINTR, errno);
// ...and check that we now receive our pending SIGALRM.
- ASSERT_EQ(1, g_sigsuspend_test_helper_call_count);
+ ASSERT_EQ(1, g_sigsuspend_signal_handler_call_count);
+}
- // Restore the original set.
- ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL));
+static int g_sigsuspend64_signal_handler_call_count = 0;
+
+TEST(signal, sigsuspend64_sigpending64) {
+ SignalMaskRestorer smr;
+
+ // Block SIGRTMIN.
+ sigset64_t just_SIGRTMIN;
+ sigemptyset64(&just_SIGRTMIN);
+ sigaddset64(&just_SIGRTMIN, SIGRTMIN);
+ ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr));
+
+ ScopedSignalHandler ssh(SIGRTMIN, [](int) { ++g_sigsuspend64_signal_handler_call_count; });
+
+ // There should be no pending signals.
+ sigset64_t pending;
+ sigemptyset64(&pending);
+ ASSERT_EQ(0, sigpending64(&pending));
+ for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) {
+ EXPECT_FALSE(sigismember64(&pending, i)) << i;
+ }
+
+ // Raise SIGRTMIN and check our signal handler wasn't called.
+ raise(SIGRTMIN);
+ ASSERT_EQ(0, g_sigsuspend64_signal_handler_call_count);
+
+ // We should now have a pending SIGRTMIN but nothing else.
+ sigemptyset64(&pending);
+ ASSERT_EQ(0, sigpending64(&pending));
+ for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) {
+ EXPECT_EQ((i == SIGRTMIN), sigismember64(&pending, i));
+ }
+
+ // Use sigsuspend64 to block everything except SIGRTMIN...
+ sigset64_t not_SIGRTMIN;
+ sigfillset64(¬_SIGRTMIN);
+ sigdelset64(¬_SIGRTMIN, SIGRTMIN);
+ ASSERT_EQ(-1, sigsuspend64(¬_SIGRTMIN));
+ ASSERT_EQ(EINTR, errno);
+ // ...and check that we now receive our pending SIGRTMIN.
+ ASSERT_EQ(1, g_sigsuspend64_signal_handler_call_count);
}
static void EmptySignalHandler(int) {}
@@ -301,12 +373,13 @@
}
TEST(signal, sigwaitinfo) {
+ SignalMaskRestorer smr;
+
// Block SIGALRM.
sigset_t just_SIGALRM;
sigemptyset(&just_SIGALRM);
sigaddset(&just_SIGALRM, SIGALRM);
- sigset_t original_set;
- ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set));
+ ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr));
// Raise SIGALRM.
sigval_t sigval;
@@ -320,38 +393,75 @@
ASSERT_EQ(0, errno);
ASSERT_EQ(SIGALRM, info.si_signo);
ASSERT_EQ(1, info.si_value.sival_int);
+}
- ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL));
+TEST(signal, sigwaitinfo64_SIGRTMIN) {
+ SignalMaskRestorer smr;
+
+ // Block SIGRTMIN.
+ sigset64_t just_SIGRTMIN;
+ sigemptyset64(&just_SIGRTMIN);
+ sigaddset64(&just_SIGRTMIN, SIGRTMIN);
+ ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr));
+
+ // Raise SIGRTMIN.
+ sigval_t sigval;
+ sigval.sival_int = 1;
+ ASSERT_EQ(0, sigqueue(getpid(), SIGRTMIN, sigval));
+
+ // Get pending SIGRTMIN.
+ siginfo_t info;
+ errno = 0;
+ ASSERT_EQ(SIGRTMIN, sigwaitinfo64(&just_SIGRTMIN, &info));
+ ASSERT_EQ(0, errno);
+ ASSERT_EQ(SIGRTMIN, info.si_signo);
+ ASSERT_EQ(1, info.si_value.sival_int);
}
TEST(signal, sigtimedwait) {
+ SignalMaskRestorer smr;
+
// Block SIGALRM.
sigset_t just_SIGALRM;
sigemptyset(&just_SIGALRM);
sigaddset(&just_SIGALRM, SIGALRM);
- sigset_t original_set;
- ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set));
+ ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr));
// Raise SIGALRM.
- sigval_t sigval;
- sigval.sival_int = 1;
+ sigval_t sigval = { .sival_int = 1 };
ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval));
// Get pending SIGALRM.
siginfo_t info;
- struct timespec timeout;
- timeout.tv_sec = 2;
- timeout.tv_nsec = 0;
+ timespec timeout = { .tv_sec = 2, .tv_nsec = 0 };
errno = 0;
ASSERT_EQ(SIGALRM, sigtimedwait(&just_SIGALRM, &info, &timeout));
ASSERT_EQ(0, errno);
+}
- ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL));
+TEST(signal, sigtimedwait64_SIGRTMIN) {
+ SignalMaskRestorer smr;
+
+ // Block SIGRTMIN.
+ sigset64_t just_SIGRTMIN;
+ sigemptyset64(&just_SIGRTMIN);
+ sigaddset64(&just_SIGRTMIN, SIGRTMIN);
+ ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr));
+
+ // Raise SIGALRM.
+ sigval_t sigval = { .sival_int = 1 };
+ ASSERT_EQ(0, sigqueue(getpid(), SIGRTMIN, sigval));
+
+ // Get pending SIGALRM.
+ siginfo_t info;
+ timespec timeout = { .tv_sec = 2, .tv_nsec = 0 };
+ errno = 0;
+ ASSERT_EQ(SIGRTMIN, sigtimedwait64(&just_SIGRTMIN, &info, &timeout));
+ ASSERT_EQ(0, errno);
}
static int64_t NanoTime() {
- struct timespec t;
- t.tv_sec = t.tv_nsec = 0;
+ timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
return static_cast<int64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
}
@@ -367,9 +477,7 @@
// Wait timeout.
int64_t start_time = NanoTime();
siginfo_t info;
- struct timespec timeout;
- timeout.tv_sec = 0;
- timeout.tv_nsec = 1000000;
+ timespec timeout = { .tv_sec = 0, .tv_nsec = 1000000 };
errno = 0;
ASSERT_EQ(-1, sigtimedwait(&just_SIGALRM, &info, &timeout));
ASSERT_EQ(EAGAIN, errno);
@@ -411,18 +519,20 @@
<< sent.si_code << ", received " << received.si_code
<< error_msg;
}
+#endif
-#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__)
TEST(signal, sigset_size) {
// The setjmp implementations for ARM, AArch64, x86, and x86_64 assume that sigset_t can fit in a
// long. This is true because ARM and x86 have broken rt signal support, and AArch64 and x86_64
// both have a SIGRTMAX defined as 64.
+#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__)
+#if defined(__BIONIC__)
static_assert(sizeof(sigset_t) <= sizeof(long), "sigset_t doesn't fit in a long");
+#endif
+ static_assert(sizeof(sigset64_t)*8 >= 64, "sigset64_t too small for real-time signals");
+#endif
}
-#endif
-#endif
-
TEST(signal, sigignore_EINVAL) {
errno = 0;
ASSERT_EQ(-1, sigignore(99999));
diff --git a/tests/spawn_test.cpp b/tests/spawn_test.cpp
index dfce0dc..84df16d 100644
--- a/tests/spawn_test.cpp
+++ b/tests/spawn_test.cpp
@@ -96,6 +96,25 @@
ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
}
+TEST(spawn, posix_spawnattr_setsigmask64_posix_spawnattr_getsigmask64) {
+ posix_spawnattr_t sa;
+ ASSERT_EQ(0, posix_spawnattr_init(&sa));
+
+ sigset64_t sigs;
+ ASSERT_EQ(0, posix_spawnattr_getsigmask64(&sa, &sigs));
+ ASSERT_FALSE(sigismember64(&sigs, SIGRTMIN));
+
+ sigset64_t just_SIGRTMIN;
+ sigemptyset64(&just_SIGRTMIN);
+ sigaddset64(&just_SIGRTMIN, SIGRTMIN);
+ ASSERT_EQ(0, posix_spawnattr_setsigmask64(&sa, &just_SIGRTMIN));
+
+ ASSERT_EQ(0, posix_spawnattr_getsigmask64(&sa, &sigs));
+ ASSERT_TRUE(sigismember64(&sigs, SIGRTMIN));
+
+ ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
+}
+
TEST(spawn, posix_spawnattr_setsigdefault_posix_spawnattr_getsigdefault) {
posix_spawnattr_t sa;
ASSERT_EQ(0, posix_spawnattr_init(&sa));
@@ -115,6 +134,25 @@
ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
}
+TEST(spawn, posix_spawnattr_setsigdefault64_posix_spawnattr_getsigdefault64) {
+ posix_spawnattr_t sa;
+ ASSERT_EQ(0, posix_spawnattr_init(&sa));
+
+ sigset64_t sigs;
+ ASSERT_EQ(0, posix_spawnattr_getsigdefault64(&sa, &sigs));
+ ASSERT_FALSE(sigismember64(&sigs, SIGRTMIN));
+
+ sigset64_t just_SIGRTMIN;
+ sigemptyset64(&just_SIGRTMIN);
+ sigaddset64(&just_SIGRTMIN, SIGRTMIN);
+ ASSERT_EQ(0, posix_spawnattr_setsigdefault64(&sa, &just_SIGRTMIN));
+
+ ASSERT_EQ(0, posix_spawnattr_getsigdefault64(&sa, &sigs));
+ ASSERT_TRUE(sigismember64(&sigs, SIGRTMIN));
+
+ ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
+}
+
TEST(spawn, posix_spawnattr_setsschedparam_posix_spawnattr_getsschedparam) {
posix_spawnattr_t sa;
ASSERT_EQ(0, posix_spawnattr_init(&sa));
diff --git a/tests/sys_epoll_test.cpp b/tests/sys_epoll_test.cpp
index d1b411a..7233ccc 100644
--- a/tests/sys_epoll_test.cpp
+++ b/tests/sys_epoll_test.cpp
@@ -35,6 +35,11 @@
// epoll_pwait without a sigset (which is equivalent to epoll_wait).
ASSERT_EQ(0, epoll_pwait(epoll_fd, events, 1, 1, NULL));
+#if defined(__BIONIC__)
+ // epoll_pwait64 without a sigset (which is equivalent to epoll_wait).
+ ASSERT_EQ(0, epoll_pwait64(epoll_fd, events, 1, 1, NULL));
+#endif
+
// epoll_pwait with a sigset.
sigset_t ss;
sigemptyset(&ss);
diff --git a/tests/sys_signalfd_test.cpp b/tests/sys_signalfd_test.cpp
new file mode 100644
index 0000000..67a72e0
--- /dev/null
+++ b/tests/sys_signalfd_test.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/signalfd.h>
+#include <unistd.h>
+
+#include <thread>
+
+#include "ScopedSignalHandler.h"
+
+static void TestSignalFd(int fd, int signal) {
+ ASSERT_NE(-1, fd) << strerror(errno);
+
+ ASSERT_EQ(0, raise(signal));
+
+ signalfd_siginfo sfd_si;
+ ASSERT_EQ(static_cast<ssize_t>(sizeof(sfd_si)), read(fd, &sfd_si, sizeof(sfd_si)));
+
+ ASSERT_EQ(signal, static_cast<int>(sfd_si.ssi_signo));
+
+ close(fd);
+}
+
+TEST(sys_signalfd, signalfd) {
+ SignalMaskRestorer smr;
+
+ sigset_t mask = {};
+ sigaddset(&mask, SIGALRM);
+ ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &mask, nullptr));
+
+ TestSignalFd(signalfd(-1, &mask, SFD_CLOEXEC), SIGALRM);
+}
+
+TEST(sys_signalfd, signalfd64) {
+#if defined(__BIONIC__)
+ SignalMaskRestorer smr;
+
+ sigset64_t mask = {};
+ sigaddset64(&mask, SIGRTMIN);
+ ASSERT_EQ(0, sigprocmask64(SIG_SETMASK, &mask, nullptr));
+
+ TestSignalFd(signalfd64(-1, &mask, SFD_CLOEXEC), SIGRTMIN);
+#endif
+}