diff --git a/libc/Android.mk b/libc/Android.mk index 340228bac..b9db2017b 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -247,6 +247,7 @@ libc_bionic_src_files := \ bionic/seteuid.cpp \ bionic/setlocale.cpp \ bionic/signalfd.cpp \ + bionic/sigprocmask.cpp \ bionic/sigwait.cpp \ bionic/statvfs.cpp \ bionic/strerror.cpp \ diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT index 090235712..cea187818 100644 --- a/libc/SYSCALLS.TXT +++ b/libc/SYSCALLS.TXT @@ -233,7 +233,6 @@ int timerfd_gettime(int, struct itimerspec*) all # signals int sigaction(int, const struct sigaction*, struct sigaction*) arm,x86,mips -int sigprocmask(int, const sigset_t*, sigset_t*) arm,x86,mips int __sigsuspend:sigsuspend(int unused1, int unused2, unsigned mask) arm,x86 int __sigsuspend:sigsuspend(const sigset_t* mask) mips int __rt_sigsuspend:rt_sigsuspend(const sigset_t *unewset, size_t sigset_size) x86_64 diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk index d28c97507..3a66c1b91 100644 --- a/libc/arch-arm/syscalls.mk +++ b/libc/arch-arm/syscalls.mk @@ -152,7 +152,6 @@ syscall_src += arch-arm/syscalls/timerfd_create.S syscall_src += arch-arm/syscalls/timerfd_settime.S syscall_src += arch-arm/syscalls/timerfd_gettime.S syscall_src += arch-arm/syscalls/sigaction.S -syscall_src += arch-arm/syscalls/sigprocmask.S syscall_src += arch-arm/syscalls/__sigsuspend.S syscall_src += arch-arm/syscalls/__rt_sigaction.S syscall_src += arch-arm/syscalls/__rt_sigprocmask.S diff --git a/libc/arch-arm/syscalls/sigprocmask.S b/libc/arch-arm/syscalls/sigprocmask.S deleted file mode 100644 index f93534065..000000000 --- a/libc/arch-arm/syscalls/sigprocmask.S +++ /dev/null @@ -1,15 +0,0 @@ -/* autogenerated by gensyscalls.py */ -#include -#include -#include - -ENTRY(sigprocmask) - mov ip, r7 - ldr r7, =__NR_sigprocmask - swi #0 - mov r7, ip - cmn r0, #(MAX_ERRNO + 1) - bxls lr - neg r0, r0 - b __set_errno -END(sigprocmask) diff --git a/libc/arch-mips/syscalls.mk b/libc/arch-mips/syscalls.mk index 4611cd8e9..740f91c49 100644 --- a/libc/arch-mips/syscalls.mk +++ b/libc/arch-mips/syscalls.mk @@ -155,7 +155,6 @@ syscall_src += arch-mips/syscalls/timerfd_create.S syscall_src += arch-mips/syscalls/timerfd_settime.S syscall_src += arch-mips/syscalls/timerfd_gettime.S syscall_src += arch-mips/syscalls/sigaction.S -syscall_src += arch-mips/syscalls/sigprocmask.S syscall_src += arch-mips/syscalls/__sigsuspend.S syscall_src += arch-mips/syscalls/__rt_sigaction.S syscall_src += arch-mips/syscalls/__rt_sigprocmask.S diff --git a/libc/arch-mips/syscalls/sigprocmask.S b/libc/arch-mips/syscalls/sigprocmask.S deleted file mode 100644 index a4049bb5e..000000000 --- a/libc/arch-mips/syscalls/sigprocmask.S +++ /dev/null @@ -1,22 +0,0 @@ -/* autogenerated by gensyscalls.py */ -#include - .text - .globl sigprocmask - .align 4 - .ent sigprocmask - -sigprocmask: - .set noreorder - .cpload $t9 - li $v0, __NR_sigprocmask - syscall - bnez $a3, 1f - move $a0, $v0 - j $ra - nop -1: - la $t9,__set_errno - j $t9 - nop - .set reorder - .end sigprocmask diff --git a/libc/arch-x86/syscalls.mk b/libc/arch-x86/syscalls.mk index 79b4f2cc3..a704905bf 100644 --- a/libc/arch-x86/syscalls.mk +++ b/libc/arch-x86/syscalls.mk @@ -156,7 +156,6 @@ syscall_src += arch-x86/syscalls/timerfd_create.S syscall_src += arch-x86/syscalls/timerfd_settime.S syscall_src += arch-x86/syscalls/timerfd_gettime.S syscall_src += arch-x86/syscalls/sigaction.S -syscall_src += arch-x86/syscalls/sigprocmask.S syscall_src += arch-x86/syscalls/__sigsuspend.S syscall_src += arch-x86/syscalls/__rt_sigaction.S syscall_src += arch-x86/syscalls/__rt_sigprocmask.S diff --git a/libc/arch-x86/syscalls/sigprocmask.S b/libc/arch-x86/syscalls/sigprocmask.S deleted file mode 100644 index 0ac052e0b..000000000 --- a/libc/arch-x86/syscalls/sigprocmask.S +++ /dev/null @@ -1,27 +0,0 @@ -/* autogenerated by gensyscalls.py */ -#include -#include -#include - -ENTRY(sigprocmask) - pushl %ebx - pushl %ecx - pushl %edx - mov 16(%esp), %ebx - mov 20(%esp), %ecx - mov 24(%esp), %edx - movl $__NR_sigprocmask, %eax - int $0x80 - cmpl $-MAX_ERRNO, %eax - jb 1f - negl %eax - pushl %eax - call __set_errno - addl $4, %esp - orl $-1, %eax -1: - popl %edx - popl %ecx - popl %ebx - ret -END(sigprocmask) diff --git a/libc/arch-x86_64/x86_64.mk b/libc/arch-x86_64/x86_64.mk index a1c170541..f293b2dbd 100644 --- a/libc/arch-x86_64/x86_64.mk +++ b/libc/arch-x86_64/x86_64.mk @@ -8,7 +8,6 @@ _LIBC_ARCH_COMMON_SRC_FILES := \ arch-x86_64/bionic/setjmp.S \ arch-x86_64/bionic/__set_tls.c \ arch-x86_64/bionic/sigaction.c \ - arch-x86_64/bionic/sigprocmask.c \ arch-x86_64/bionic/sigsetjmp.S \ arch-x86_64/bionic/sigsuspend.c \ arch-x86_64/bionic/syscall.S \ diff --git a/libc/bionic/pthread_sigmask.cpp b/libc/bionic/pthread_sigmask.cpp index e4e1b2b98..79f31a145 100644 --- a/libc/bionic/pthread_sigmask.cpp +++ b/libc/bionic/pthread_sigmask.cpp @@ -31,31 +31,9 @@ #include #include "private/ErrnoRestorer.h" -#include "private/kernel_sigset_t.h" -extern "C" int __rt_sigprocmask(int, const kernel_sigset_t*, kernel_sigset_t*, size_t); - -int pthread_sigmask(int how, const sigset_t* iset, sigset_t* oset) { +int pthread_sigmask(int how, const sigset_t* new_set, sigset_t* old_set) { ErrnoRestorer errno_restorer; - - // 'in_set_ptr' is the second parameter to __rt_sigprocmask. It must be NULL - // if 'set' is NULL to ensure correct semantics (which in this case would - // be to ignore 'how' and return the current signal set into 'oset'). - kernel_sigset_t in_set; - kernel_sigset_t* in_set_ptr = NULL; - if (iset != NULL) { - in_set.set(iset); - in_set_ptr = &in_set; - } - - kernel_sigset_t out_set; - if (__rt_sigprocmask(how, in_set_ptr, &out_set, sizeof(out_set)) == -1) { - return errno; - } - - if (oset != NULL) { - *oset = out_set.bionic; - } - - return 0; + int result = sigprocmask(how, new_set, old_set); + return (result == -1) ? errno : 0; } diff --git a/libc/arch-x86_64/bionic/sigprocmask.c b/libc/bionic/sigprocmask.cpp similarity index 69% rename from libc/arch-x86_64/bionic/sigprocmask.c rename to libc/bionic/sigprocmask.cpp index cdafa083e..61e2c633a 100644 --- a/libc/arch-x86_64/bionic/sigprocmask.c +++ b/libc/bionic/sigprocmask.cpp @@ -26,10 +26,30 @@ * SUCH DAMAGE. */ +#include +#include #include -extern int __rt_sigprocmask(int, const sigset_t*, sigset_t*, size_t); +#include "private/kernel_sigset_t.h" -int sigprocmask(int how, const sigset_t* set, sigset_t* old_set) { - return __rt_sigprocmask(how, set, old_set, sizeof(sigset_t)); +extern "C" int __rt_sigprocmask(int, const kernel_sigset_t*, kernel_sigset_t*, size_t); + +int sigprocmask(int how, const sigset_t* bionic_new_set, sigset_t* bionic_old_set) { + kernel_sigset_t new_set; + kernel_sigset_t* new_set_ptr = NULL; + if (bionic_new_set != NULL) { + new_set.set(bionic_new_set); + new_set_ptr = &new_set; + } + + kernel_sigset_t old_set; + if (__rt_sigprocmask(how, new_set_ptr, &old_set, sizeof(old_set)) == -1) { + return -1; + } + + if (bionic_old_set != NULL) { + *bionic_old_set = old_set.bionic; + } + + return 0; } diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp index d82921b30..4a7c155c0 100644 --- a/tests/pthread_test.cpp +++ b/tests/pthread_test.cpp @@ -173,12 +173,28 @@ static void* SignalHandlerFn(void* arg) { } TEST(pthread, pthread_sigmask) { + // Check that SIGUSR1 isn't blocked. + sigset_t original_set; + sigemptyset(&original_set); + ASSERT_EQ(0, pthread_sigmask(SIG_BLOCK, NULL, &original_set)); + ASSERT_FALSE(sigismember(&original_set, SIGUSR1)); + // Block SIGUSR1. sigset_t set; sigemptyset(&set); sigaddset(&set, SIGUSR1); ASSERT_EQ(0, pthread_sigmask(SIG_BLOCK, &set, NULL)); + // Check that SIGUSR1 is blocked. + sigset_t final_set; + sigemptyset(&final_set); + ASSERT_EQ(0, pthread_sigmask(SIG_BLOCK, NULL, &final_set)); + ASSERT_TRUE(sigismember(&final_set, SIGUSR1)); + // ...and that sigprocmask agrees with pthread_sigmask. + sigemptyset(&final_set); + ASSERT_EQ(0, sigprocmask(SIG_BLOCK, NULL, &final_set)); + ASSERT_TRUE(sigismember(&final_set, SIGUSR1)); + // Spawn a thread that calls sigwait and tells us what it received. pthread_t signal_thread; int received_signal = -1; @@ -192,6 +208,9 @@ TEST(pthread, pthread_sigmask) { ASSERT_EQ(0, pthread_join(signal_thread, &join_result)); ASSERT_EQ(SIGUSR1, received_signal); ASSERT_EQ(0U, reinterpret_cast(join_result)); + + // Restore the original signal mask. + ASSERT_EQ(0, pthread_sigmask(SIG_SETMASK, &original_set, NULL)); } #if __BIONIC__