diff --git a/libc/Android.mk b/libc/Android.mk index f04cf5cd5..6863151de 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -204,8 +204,11 @@ libc_bionic_src_files := \ bionic/signalfd.cpp \ bionic/sigpending.cpp \ bionic/sigprocmask.cpp \ + bionic/sigqueue.cpp \ bionic/sigsuspend.cpp \ + bionic/sigtimedwait.cpp \ bionic/sigwait.cpp \ + bionic/sigwaitinfo.cpp \ bionic/socket.cpp \ bionic/stat.cpp \ bionic/statvfs.cpp \ diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT index d9ede2f8e..a648c9fef 100644 --- a/libc/SYSCALLS.TXT +++ b/libc/SYSCALLS.TXT @@ -223,6 +223,7 @@ int __rt_sigpending:rt_sigpending(sigset_t*, size_t) all int __rt_sigprocmask:rt_sigprocmask(int, const sigset_t*, sigset_t*, size_t) all int __rt_sigsuspend:rt_sigsuspend(const sigset_t*, size_t) all int __rt_sigtimedwait:rt_sigtimedwait(const sigset_t*, struct siginfo_t*, struct timespec_t*, size_t) all +int __rt_sigqueueinfo:rt_sigqueueinfo(pid_t, int, siginfo_t*) all int __signalfd4:signalfd4(int, const sigset_t*, size_t, int) all # sockets diff --git a/libc/arch-arm/syscalls/__rt_sigqueueinfo.S b/libc/arch-arm/syscalls/__rt_sigqueueinfo.S new file mode 100644 index 000000000..c823ceee1 --- /dev/null +++ b/libc/arch-arm/syscalls/__rt_sigqueueinfo.S @@ -0,0 +1,14 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(__rt_sigqueueinfo) + mov ip, r7 + ldr r7, =__NR_rt_sigqueueinfo + swi #0 + mov r7, ip + cmn r0, #(MAX_ERRNO + 1) + bxls lr + neg r0, r0 + b __set_errno_internal +END(__rt_sigqueueinfo) diff --git a/libc/arch-arm64/syscalls/__rt_sigqueueinfo.S b/libc/arch-arm64/syscalls/__rt_sigqueueinfo.S new file mode 100644 index 000000000..2b23e1822 --- /dev/null +++ b/libc/arch-arm64/syscalls/__rt_sigqueueinfo.S @@ -0,0 +1,15 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(__rt_sigqueueinfo) + mov x8, __NR_rt_sigqueueinfo + svc #0 + + cmn x0, #(MAX_ERRNO + 1) + cneg x0, x0, hi + b.hi __set_errno_internal + + ret +END(__rt_sigqueueinfo) +.hidden __rt_sigqueueinfo diff --git a/libc/arch-mips/syscalls/__rt_sigqueueinfo.S b/libc/arch-mips/syscalls/__rt_sigqueueinfo.S new file mode 100644 index 000000000..a978bc467 --- /dev/null +++ b/libc/arch-mips/syscalls/__rt_sigqueueinfo.S @@ -0,0 +1,19 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(__rt_sigqueueinfo) + .set noreorder + .cpload t9 + li v0, __NR_rt_sigqueueinfo + syscall + bnez a3, 1f + move a0, v0 + j ra + nop +1: + la t9,__set_errno_internal + j t9 + nop + .set reorder +END(__rt_sigqueueinfo) diff --git a/libc/arch-mips64/syscalls/__rt_sigqueueinfo.S b/libc/arch-mips64/syscalls/__rt_sigqueueinfo.S new file mode 100644 index 000000000..e97aebad3 --- /dev/null +++ b/libc/arch-mips64/syscalls/__rt_sigqueueinfo.S @@ -0,0 +1,26 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(__rt_sigqueueinfo) + .set push + .set noreorder + li v0, __NR_rt_sigqueueinfo + syscall + bnez a3, 1f + move a0, v0 + j ra + nop +1: + move t0, ra + bal 2f + nop +2: + .cpsetup ra, t1, 2b + LA t9,__set_errno_internal + .cpreturn + j t9 + move ra, t0 + .set pop +END(__rt_sigqueueinfo) +.hidden __rt_sigqueueinfo diff --git a/libc/arch-x86/syscalls/__rt_sigqueueinfo.S b/libc/arch-x86/syscalls/__rt_sigqueueinfo.S new file mode 100644 index 000000000..415210067 --- /dev/null +++ b/libc/arch-x86/syscalls/__rt_sigqueueinfo.S @@ -0,0 +1,31 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(__rt_sigqueueinfo) + pushl %ebx + .cfi_def_cfa_offset 8 + .cfi_rel_offset ebx, 0 + pushl %ecx + .cfi_adjust_cfa_offset 4 + .cfi_rel_offset ecx, 0 + pushl %edx + .cfi_adjust_cfa_offset 4 + .cfi_rel_offset edx, 0 + mov 16(%esp), %ebx + mov 20(%esp), %ecx + mov 24(%esp), %edx + movl $__NR_rt_sigqueueinfo, %eax + int $0x80 + cmpl $-MAX_ERRNO, %eax + jb 1f + negl %eax + pushl %eax + call __set_errno_internal + addl $4, %esp +1: + popl %edx + popl %ecx + popl %ebx + ret +END(__rt_sigqueueinfo) diff --git a/libc/arch-x86_64/syscalls/__rt_sigqueueinfo.S b/libc/arch-x86_64/syscalls/__rt_sigqueueinfo.S new file mode 100644 index 000000000..52b686346 --- /dev/null +++ b/libc/arch-x86_64/syscalls/__rt_sigqueueinfo.S @@ -0,0 +1,16 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include + +ENTRY(__rt_sigqueueinfo) + movl $__NR_rt_sigqueueinfo, %eax + syscall + cmpq $-MAX_ERRNO, %rax + jb 1f + negl %eax + movl %eax, %edi + call __set_errno_internal +1: + ret +END(__rt_sigqueueinfo) +.hidden __rt_sigqueueinfo diff --git a/libc/bionic/sigqueue.cpp b/libc/bionic/sigqueue.cpp new file mode 100644 index 000000000..39c879873 --- /dev/null +++ b/libc/bionic/sigqueue.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2014 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 +#include +#include +#include + +extern "C" int __rt_sigqueueinfo(pid_t, int, siginfo_t*); + +int sigqueue(pid_t pid, int signo, const sigval value) { + siginfo_t info; + memset(&info, 0, sizeof(siginfo_t)); + info.si_signo = signo; + info.si_code = SI_QUEUE; + info.si_pid = getpid(); + info.si_uid = getuid(); + info.si_value = value; + + return __rt_sigqueueinfo(pid, signo, &info); +} diff --git a/libc/bionic/sigtimedwait.cpp b/libc/bionic/sigtimedwait.cpp new file mode 100644 index 000000000..c29f806e9 --- /dev/null +++ b/libc/bionic/sigtimedwait.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2014 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 + +#include "private/kernel_sigset_t.h" + +extern "C" int __rt_sigtimedwait(const sigset_t*, siginfo_t*, const timespec*, size_t); + +int sigtimedwait(const sigset_t* set, siginfo_t* info, const timespec* timeout) { + kernel_sigset_t sigset(set); + return __rt_sigtimedwait(sigset.get(), info, timeout, sizeof(sigset)); +} diff --git a/libc/bionic/sigwaitinfo.cpp b/libc/bionic/sigwaitinfo.cpp new file mode 100644 index 000000000..43e2395e6 --- /dev/null +++ b/libc/bionic/sigwaitinfo.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2014 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 + +int sigwaitinfo(const sigset_t* set, siginfo_t* info) { + return sigtimedwait(set, info, NULL); +} diff --git a/libc/include/machine/posix_limits.h b/libc/include/machine/posix_limits.h index 4ffe421f6..787af5c21 100644 --- a/libc/include/machine/posix_limits.h +++ b/libc/include/machine/posix_limits.h @@ -69,7 +69,7 @@ #define _POSIX_PRIORITIZED_IO -1 /* not implemented */ #define _POSIX_RAW_SOCKETS 200809L #define _POSIX_READER_WRITER_LOCKS 200809L -#define _POSIX_REALTIME_SIGNALS -1 /* for now, this is not supported */ +#define _POSIX_REALTIME_SIGNALS 200809L #define _POSIX_REGEXP 1 #define _POSIX_RE_DUP_MAX 255 #define _POSIX_SAVED_IDS 1 /* saved user ids is a Linux feature */ diff --git a/libc/include/signal.h b/libc/include/signal.h index 6d89ef7d0..867f49748 100644 --- a/libc/include/signal.h +++ b/libc/include/signal.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -133,6 +134,10 @@ extern void psignal(int, const char*); extern int pthread_kill(pthread_t, int); extern int pthread_sigmask(int, const sigset_t*, sigset_t*); +extern int sigqueue(pid_t, int, const union sigval); +extern int sigtimedwait(const sigset_t*, siginfo_t*, const struct timespec*); +extern int sigwaitinfo(const sigset_t*, siginfo_t*); + __END_DECLS #endif /* _SIGNAL_H_ */ diff --git a/tests/ScopedSignalHandler.h b/tests/ScopedSignalHandler.h index 3ec23b0d8..3fb60a164 100644 --- a/tests/ScopedSignalHandler.h +++ b/tests/ScopedSignalHandler.h @@ -18,17 +18,27 @@ #define _BIONIC_TESTS_SCOPED_SIGNAL_HANDLER_H #include +#include 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 797468efe..f63d1ee93 100644 --- a/tests/pthread_test.cpp +++ b/tests/pthread_test.cpp @@ -178,17 +178,34 @@ static void* IdFn(void* arg) { return arg; } -static void* SleepFn(void* arg) { - sleep(reinterpret_cast(arg)); - return NULL; -} - -static void* SpinFn(void* arg) { - volatile bool* b = reinterpret_cast(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(pthread_join(reinterpret_cast(arg), NULL)); @@ -229,8 +246,10 @@ TEST(pthread, pthread_create_EAGAIN) { } TEST(pthread, pthread_no_join_after_detach) { + SpinFunctionHelper spinhelper; + pthread_t t1; - ASSERT_EQ(0, pthread_create(&t1, NULL, SleepFn, reinterpret_cast(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_join_after_detach) { } 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 @@ TEST(pthread, pthread_no_op_detach_after_join) { 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__self) { } TEST(pthread, pthread_setname_np__other) { + SpinFunctionHelper spinhelper; + pthread_t t1; - ASSERT_EQ(0, pthread_create(&t1, NULL, SleepFn, reinterpret_cast(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_detach__leak) { } TEST(pthread, pthread_getcpuclockid__clock_gettime) { + SpinFunctionHelper spinhelper; + pthread_t t; - ASSERT_EQ(0, pthread_create(&t, NULL, SleepFn, reinterpret_cast(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_kill__no_such_thread) { } 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(t1))); @@ -514,7 +537,7 @@ TEST(pthread, pthread_join__multijoin) { // 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 8fd8b72f7..f8fdc3f99 100644 --- a/tests/signal_test.cpp +++ b/tests/signal_test.cpp @@ -16,9 +16,10 @@ #include -#include #include +#include + #include "ScopedSignalHandler.h" static size_t SIGNAL_MIN() { @@ -276,3 +277,101 @@ TEST(signal, limits) { // 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(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 fd27682db..96d66e48d 100644 --- a/tests/unistd_test.cpp +++ b/tests/unistd_test.cpp @@ -556,6 +556,7 @@ TEST(unistd, _POSIX_macros_smoke) { 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 @@ TEST(unistd, _POSIX_macros_smoke) { EXPECT_EQ(-1, _POSIX_BARRIERS); 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); @@ -704,6 +704,7 @@ TEST(unistd, sysconf) { 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 @@ TEST(unistd, sysconf) { VERIFY_SYSCONF_NOT_SUPPORT(_SC_BARRIERS); 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);