support _POSIX_REALTIME_SIGNALS
Bug: 18489947
Change-Id: I2e834d68bc10ca5fc7ebde047b517a3074179475
diff --git a/tests/ScopedSignalHandler.h b/tests/ScopedSignalHandler.h
index 3ec23b0..3fb60a1 100644
--- a/tests/ScopedSignalHandler.h
+++ b/tests/ScopedSignalHandler.h
@@ -18,17 +18,27 @@
#define _BIONIC_TESTS_SCOPED_SIGNAL_HANDLER_H
#include <signal.h>
+#include <string.h>
class ScopedSignalHandler {
public:
ScopedSignalHandler(int signal_number, void (*handler)(int), int sa_flags = 0)
: signal_number_(signal_number) {
- sigemptyset(&action_.sa_mask);
+ memset(&action_, 0, sizeof(action_));
action_.sa_flags = sa_flags;
action_.sa_handler = handler;
sigaction(signal_number_, &action_, &old_action_);
}
+ ScopedSignalHandler(int signal_number, void (*action)(int, siginfo_t*, void*),
+ int sa_flags = SA_SIGINFO)
+ : signal_number_(signal_number) {
+ memset(&action_, 0, sizeof(action_));
+ action_.sa_flags = sa_flags;
+ action_.sa_sigaction = action;
+ sigaction(signal_number_, &action_, &old_action_);
+ }
+
~ScopedSignalHandler() {
sigaction(signal_number_, &old_action_, NULL);
}
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 797468e..f63d1ee 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -178,17 +178,34 @@
return arg;
}
-static void* SleepFn(void* arg) {
- sleep(reinterpret_cast<uintptr_t>(arg));
- return NULL;
-}
-
-static void* SpinFn(void* arg) {
- volatile bool* b = reinterpret_cast<volatile bool*>(arg);
- while (!*b) {
+class SpinFunctionHelper {
+ public:
+ SpinFunctionHelper() {
+ SpinFunctionHelper::spin_flag_ = true;
}
- return NULL;
-}
+ ~SpinFunctionHelper() {
+ UnSpin();
+ }
+ auto GetFunction() -> void* (*)(void*) {
+ return SpinFunctionHelper::SpinFn;
+ }
+
+ void UnSpin() {
+ SpinFunctionHelper::spin_flag_ = false;
+ }
+
+ private:
+ static void* SpinFn(void*) {
+ while (spin_flag_) {}
+ return NULL;
+ }
+ static volatile bool spin_flag_;
+};
+
+// It doesn't matter if spin_flag_ is used in several tests,
+// because it is always set to false after each test. Each thread
+// loops on spin_flag_ can find it becomes false at some time.
+volatile bool SpinFunctionHelper::spin_flag_ = false;
static void* JoinFn(void* arg) {
return reinterpret_cast<void*>(pthread_join(reinterpret_cast<pthread_t>(arg), NULL));
@@ -229,8 +246,10 @@
}
TEST(pthread, pthread_no_join_after_detach) {
+ SpinFunctionHelper spinhelper;
+
pthread_t t1;
- ASSERT_EQ(0, pthread_create(&t1, NULL, SleepFn, reinterpret_cast<void*>(5)));
+ ASSERT_EQ(0, pthread_create(&t1, NULL, spinhelper.GetFunction(), NULL));
// After a pthread_detach...
ASSERT_EQ(0, pthread_detach(t1));
@@ -241,10 +260,10 @@
}
TEST(pthread, pthread_no_op_detach_after_join) {
- bool done = false;
+ SpinFunctionHelper spinhelper;
pthread_t t1;
- ASSERT_EQ(0, pthread_create(&t1, NULL, SpinFn, &done));
+ ASSERT_EQ(0, pthread_create(&t1, NULL, spinhelper.GetFunction(), NULL));
// If thread 2 is already waiting to join thread 1...
pthread_t t2;
@@ -256,7 +275,7 @@
ASSERT_EQ(0, pthread_detach(t1));
AssertDetached(t1, false);
- done = true;
+ spinhelper.UnSpin();
// ...but t2's join on t1 still goes ahead (which we can tell because our join on t2 finishes).
void* join_result;
@@ -369,8 +388,10 @@
}
TEST(pthread, pthread_setname_np__other) {
+ SpinFunctionHelper spinhelper;
+
pthread_t t1;
- ASSERT_EQ(0, pthread_create(&t1, NULL, SleepFn, reinterpret_cast<void*>(5)));
+ ASSERT_EQ(0, pthread_create(&t1, NULL, spinhelper.GetFunction(), NULL));
ASSERT_EQ(0, pthread_setname_np(t1, "short 2"));
}
@@ -451,8 +472,10 @@
}
TEST(pthread, pthread_getcpuclockid__clock_gettime) {
+ SpinFunctionHelper spinhelper;
+
pthread_t t;
- ASSERT_EQ(0, pthread_create(&t, NULL, SleepFn, reinterpret_cast<void*>(5)));
+ ASSERT_EQ(0, pthread_create(&t, NULL, spinhelper.GetFunction(), NULL));
clockid_t c;
ASSERT_EQ(0, pthread_getcpuclockid(t, &c));
@@ -501,10 +524,10 @@
}
TEST(pthread, pthread_join__multijoin) {
- bool done = false;
+ SpinFunctionHelper spinhelper;
pthread_t t1;
- ASSERT_EQ(0, pthread_create(&t1, NULL, SpinFn, &done));
+ ASSERT_EQ(0, pthread_create(&t1, NULL, spinhelper.GetFunction(), NULL));
pthread_t t2;
ASSERT_EQ(0, pthread_create(&t2, NULL, JoinFn, reinterpret_cast<void*>(t1)));
@@ -514,7 +537,7 @@
// Multiple joins to the same thread should fail.
ASSERT_EQ(EINVAL, pthread_join(t1, NULL));
- done = true;
+ spinhelper.UnSpin();
// ...but t2's join on t1 still goes ahead (which we can tell because our join on t2 finishes).
void* join_result;
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index 8fd8b72..f8fdc3f 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -16,9 +16,10 @@
#include <signal.h>
-#include <errno.h>
#include <gtest/gtest.h>
+#include <errno.h>
+
#include "ScopedSignalHandler.h"
static size_t SIGNAL_MIN() {
@@ -276,3 +277,101 @@
// We don't currently reserve any at the top.
ASSERT_EQ(SIGRTMAX, __SIGRTMAX);
}
+
+static int g_sigqueue_signal_handler_call_count = 0;
+
+static void SigqueueSignalHandler(int signum, siginfo_t* info, void*) {
+ ASSERT_EQ(SIGALRM, signum);
+ ASSERT_EQ(SIGALRM, info->si_signo);
+ ASSERT_EQ(SI_QUEUE, info->si_code);
+ ASSERT_EQ(1, info->si_value.sival_int);
+ ++g_sigqueue_signal_handler_call_count;
+}
+
+TEST(signal, sigqueue) {
+ ScopedSignalHandler ssh(SIGALRM, SigqueueSignalHandler, SA_SIGINFO);
+ sigval_t sigval;
+ sigval.sival_int = 1;
+ errno = 0;
+ ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval));
+ ASSERT_EQ(0, errno);
+ ASSERT_EQ(1, g_sigqueue_signal_handler_call_count);
+}
+
+TEST(signal, sigwaitinfo) {
+ // 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));
+
+ // Raise SIGALRM.
+ sigval_t sigval;
+ sigval.sival_int = 1;
+ ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval));
+
+ // Get pending SIGALRM.
+ siginfo_t info;
+ errno = 0;
+ ASSERT_EQ(SIGALRM, sigwaitinfo(&just_SIGALRM, &info));
+ 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, sigtimedwait) {
+ // 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));
+
+ // Raise SIGALRM.
+ sigval_t sigval;
+ 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;
+ errno = 0;
+ ASSERT_EQ(SIGALRM, sigtimedwait(&just_SIGALRM, &info, &timeout));
+ ASSERT_EQ(0, errno);
+
+ ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL));
+}
+
+static int64_t NanoTime() {
+ struct timespec t;
+ t.tv_sec = t.tv_nsec = 0;
+ clock_gettime(CLOCK_MONOTONIC, &t);
+ return static_cast<int64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
+}
+
+TEST(signal, sigtimedwait_timeout) {
+ // 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));
+
+ // Wait timeout.
+ int64_t start_time = NanoTime();
+ siginfo_t info;
+ struct timespec timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 1000000;
+ errno = 0;
+ ASSERT_EQ(-1, sigtimedwait(&just_SIGALRM, &info, &timeout));
+ ASSERT_EQ(EAGAIN, errno);
+ ASSERT_GE(NanoTime() - start_time, 1000000);
+
+ ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL));
+}
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index f0aeb09..433c1b5 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -554,6 +554,7 @@
EXPECT_EQ(_POSIX_VERSION, _POSIX_PRIORITY_SCHEDULING);
EXPECT_EQ(_POSIX_VERSION, _POSIX_RAW_SOCKETS);
EXPECT_EQ(_POSIX_VERSION, _POSIX_READER_WRITER_LOCKS);
+ EXPECT_EQ(_POSIX_VERSION, _POSIX_REALTIME_SIGNALS);
EXPECT_GT(_POSIX_REGEXP, 0);
EXPECT_GT(_POSIX_RE_DUP_MAX, 0);
EXPECT_GT(_POSIX_SAVED_IDS, 0);
@@ -617,7 +618,6 @@
EXPECT_EQ(-1, _POSIX_CPUTIME);
EXPECT_EQ(-1, _POSIX_MESSAGE_PASSING);
EXPECT_EQ(-1, _POSIX_PRIORITIZED_IO);
- EXPECT_EQ(-1, _POSIX_REALTIME_SIGNALS);
EXPECT_EQ(-1, _POSIX_SHARED_MEMORY_OBJECTS);
EXPECT_EQ(-1, _POSIX_SPAWN);
EXPECT_EQ(-1, _POSIX_SPIN_LOCKS);
@@ -702,6 +702,7 @@
VERIFY_SYSCONF_POSIX_VERSION(_SC_MEMLOCK_RANGE);
VERIFY_SYSCONF_POSIX_VERSION(_SC_MEMORY_PROTECTION);
VERIFY_SYSCONF_POSIX_VERSION(_SC_PRIORITY_SCHEDULING);
+ VERIFY_SYSCONF_POSIX_VERSION(_SC_REALTIME_SIGNALS);
VERIFY_SYSCONF_POSIX_VERSION(_SC_SEMAPHORES);
VERIFY_SYSCONF_POSIX_VERSION(_SC_SYNCHRONIZED_IO);
VERIFY_SYSCONF_POSIX_VERSION(_SC_TIMERS);
@@ -778,7 +779,6 @@
VERIFY_SYSCONF_NOT_SUPPORT(_SC_CPUTIME);
VERIFY_SYSCONF_NOT_SUPPORT(_SC_MESSAGE_PASSING);
VERIFY_SYSCONF_NOT_SUPPORT(_SC_PRIORITIZED_IO);
- VERIFY_SYSCONF_NOT_SUPPORT(_SC_REALTIME_SIGNALS);
VERIFY_SYSCONF_NOT_SUPPORT(_SC_SHARED_MEMORY_OBJECTS);
VERIFY_SYSCONF_NOT_SUPPORT(_SC_SPAWN);
VERIFY_SYSCONF_NOT_SUPPORT(_SC_SPIN_LOCKS);