am 94926f8c
: Merge "support _POSIX_REALTIME_SIGNALS"
* commit '94926f8cfa0adf37c4e19256ade7261a97f72e51': support _POSIX_REALTIME_SIGNALS
This commit is contained in:
commit
e0601bd49f
17 changed files with 403 additions and 24 deletions
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
14
libc/arch-arm/syscalls/__rt_sigqueueinfo.S
Normal file
14
libc/arch-arm/syscalls/__rt_sigqueueinfo.S
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
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)
|
15
libc/arch-arm64/syscalls/__rt_sigqueueinfo.S
Normal file
15
libc/arch-arm64/syscalls/__rt_sigqueueinfo.S
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
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
|
19
libc/arch-mips/syscalls/__rt_sigqueueinfo.S
Normal file
19
libc/arch-mips/syscalls/__rt_sigqueueinfo.S
Normal file
|
@ -0,0 +1,19 @@
|
|||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
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)
|
26
libc/arch-mips64/syscalls/__rt_sigqueueinfo.S
Normal file
26
libc/arch-mips64/syscalls/__rt_sigqueueinfo.S
Normal file
|
@ -0,0 +1,26 @@
|
|||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
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
|
31
libc/arch-x86/syscalls/__rt_sigqueueinfo.S
Normal file
31
libc/arch-x86/syscalls/__rt_sigqueueinfo.S
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
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)
|
16
libc/arch-x86_64/syscalls/__rt_sigqueueinfo.S
Normal file
16
libc/arch-x86_64/syscalls/__rt_sigqueueinfo.S
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
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
|
46
libc/bionic/sigqueue.cpp
Normal file
46
libc/bionic/sigqueue.cpp
Normal file
|
@ -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 <signal.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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);
|
||||
}
|
38
libc/bionic/sigtimedwait.cpp
Normal file
38
libc/bionic/sigtimedwait.cpp
Normal file
|
@ -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 <signal.h>
|
||||
|
||||
#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));
|
||||
}
|
33
libc/bionic/sigwaitinfo.cpp
Normal file
33
libc/bionic/sigwaitinfo.cpp
Normal file
|
@ -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 <signal.h>
|
||||
|
||||
int sigwaitinfo(const sigset_t* set, siginfo_t* info) {
|
||||
return sigtimedwait(set, info, NULL);
|
||||
}
|
|
@ -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 */
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <asm/sigcontext.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <linux/time.h>
|
||||
#include <machine/pthread_types.h>
|
||||
#include <string.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
@ -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_ */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -178,17 +178,34 @@ static void* IdFn(void* arg) {
|
|||
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_create_EAGAIN) {
|
|||
}
|
||||
|
||||
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_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<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_detach__leak) {
|
|||
}
|
||||
|
||||
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_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<void*>(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;
|
||||
|
|
|
@ -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 @@ 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<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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue