summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libc/Android.mk8
-rw-r--r--libc/SYSCALLS.TXT2
-rw-r--r--libc/arch-arm/syscalls.mk2
-rw-r--r--libc/arch-arm/syscalls/__sigaction.S (renamed from libc/arch-arm/syscalls/sigaction.S)4
-rw-r--r--libc/arch-mips/syscalls.mk2
-rw-r--r--libc/arch-mips/syscalls/__sigaction.S (renamed from libc/arch-mips/syscalls/sigaction.S)8
-rw-r--r--libc/arch-x86/syscalls.mk2
-rw-r--r--libc/arch-x86/syscalls/__sigaction.S (renamed from libc/arch-x86/syscalls/sigaction.S)4
-rw-r--r--libc/arch-x86_64/x86_64.mk1
-rw-r--r--libc/bionic/sigaction.cpp76
-rw-r--r--libc/bionic/sigaddset.cpp (renamed from libc/arch-x86_64/bionic/sigaction.c)30
-rw-r--r--libc/bionic/sigdelset.cpp40
-rw-r--r--libc/bionic/sigemptyset.cpp38
-rw-r--r--libc/bionic/sigfillset.cpp38
-rw-r--r--libc/bionic/sigismember.cpp39
-rw-r--r--libc/bionic/signal.cpp (renamed from libc/bionic/signal.c)35
-rw-r--r--libc/include/signal.h107
-rw-r--r--linker/debugger.cpp9
-rw-r--r--tests/pthread_test.cpp4
-rw-r--r--tests/signal_test.cpp41
20 files changed, 361 insertions, 129 deletions
diff --git a/libc/Android.mk b/libc/Android.mk
index 417d0ab..72b6dc8 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -125,7 +125,6 @@ libc_common_src_files := \
bionic/sigblock.c \
bionic/siginterrupt.c \
bionic/siglist.c \
- bionic/signal.c \
bionic/signame.c \
bionic/sigsetmask.c \
bionic/sleep.c \
@@ -246,6 +245,13 @@ libc_bionic_src_files := \
bionic/seteuid.cpp \
bionic/setlocale.cpp \
bionic/signalfd.cpp \
+ bionic/sigaction.cpp \
+ bionic/sigaddset.cpp \
+ bionic/sigdelset.cpp \
+ bionic/sigemptyset.cpp \
+ bionic/sigfillset.cpp \
+ bionic/sigismember.cpp \
+ bionic/signal.cpp \
bionic/sigpending.cpp \
bionic/sigprocmask.cpp \
bionic/sigsuspend.cpp \
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index f5712e1..e5e3c4d 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -224,7 +224,7 @@ int timerfd_settime(int, int, const struct itimerspec*, struct itimers
int timerfd_gettime(int, struct itimerspec*) all
# signals
-int sigaction(int, const struct sigaction*, struct sigaction*) arm,x86,mips
+int __sigaction:sigaction(int, const struct sigaction*, struct sigaction*) arm,mips,x86
int __rt_sigaction:rt_sigaction(int, const struct sigaction*, struct sigaction*, size_t) all
int __rt_sigpending:rt_sigpending(sigset_t*, size_t) all
int __rt_sigprocmask:rt_sigprocmask(int, const sigset_t*, sigset_t*, size_t) all
diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk
index 315d730..f9d348b 100644
--- a/libc/arch-arm/syscalls.mk
+++ b/libc/arch-arm/syscalls.mk
@@ -22,6 +22,7 @@ syscall_src += arch-arm/syscalls/__rt_sigsuspend.S
syscall_src += arch-arm/syscalls/__rt_sigtimedwait.S
syscall_src += arch-arm/syscalls/__sched_getaffinity.S
syscall_src += arch-arm/syscalls/__set_tls.S
+syscall_src += arch-arm/syscalls/__sigaction.S
syscall_src += arch-arm/syscalls/__statfs64.S
syscall_src += arch-arm/syscalls/__sys_clone.S
syscall_src += arch-arm/syscalls/__syslog.S
@@ -178,7 +179,6 @@ syscall_src += arch-arm/syscalls/settimeofday.S
syscall_src += arch-arm/syscalls/setuid.S
syscall_src += arch-arm/syscalls/setxattr.S
syscall_src += arch-arm/syscalls/shutdown.S
-syscall_src += arch-arm/syscalls/sigaction.S
syscall_src += arch-arm/syscalls/sigaltstack.S
syscall_src += arch-arm/syscalls/signalfd4.S
syscall_src += arch-arm/syscalls/socket.S
diff --git a/libc/arch-arm/syscalls/sigaction.S b/libc/arch-arm/syscalls/__sigaction.S
index 65e8840..23a2b23 100644
--- a/libc/arch-arm/syscalls/sigaction.S
+++ b/libc/arch-arm/syscalls/__sigaction.S
@@ -4,7 +4,7 @@
#include <linux/err.h>
#include <machine/asm.h>
-ENTRY(sigaction)
+ENTRY(__sigaction)
mov ip, r7
ldr r7, =__NR_sigaction
swi #0
@@ -13,4 +13,4 @@ ENTRY(sigaction)
bxls lr
neg r0, r0
b __set_errno
-END(sigaction)
+END(__sigaction)
diff --git a/libc/arch-mips/syscalls.mk b/libc/arch-mips/syscalls.mk
index 4e7b65b..fc96222 100644
--- a/libc/arch-mips/syscalls.mk
+++ b/libc/arch-mips/syscalls.mk
@@ -22,6 +22,7 @@ syscall_src += arch-mips/syscalls/__rt_sigsuspend.S
syscall_src += arch-mips/syscalls/__rt_sigtimedwait.S
syscall_src += arch-mips/syscalls/__sched_getaffinity.S
syscall_src += arch-mips/syscalls/__set_thread_area.S
+syscall_src += arch-mips/syscalls/__sigaction.S
syscall_src += arch-mips/syscalls/__statfs64.S
syscall_src += arch-mips/syscalls/__sys_clone.S
syscall_src += arch-mips/syscalls/__syslog.S
@@ -179,7 +180,6 @@ syscall_src += arch-mips/syscalls/settimeofday.S
syscall_src += arch-mips/syscalls/setuid.S
syscall_src += arch-mips/syscalls/setxattr.S
syscall_src += arch-mips/syscalls/shutdown.S
-syscall_src += arch-mips/syscalls/sigaction.S
syscall_src += arch-mips/syscalls/sigaltstack.S
syscall_src += arch-mips/syscalls/signalfd4.S
syscall_src += arch-mips/syscalls/socket.S
diff --git a/libc/arch-mips/syscalls/sigaction.S b/libc/arch-mips/syscalls/__sigaction.S
index d1808c6..cc53ab4 100644
--- a/libc/arch-mips/syscalls/sigaction.S
+++ b/libc/arch-mips/syscalls/__sigaction.S
@@ -2,11 +2,11 @@
#include <asm/unistd.h>
.text
- .globl sigaction
+ .globl __sigaction
.align 4
- .ent sigaction
+ .ent __sigaction
-sigaction:
+__sigaction:
.set noreorder
.cpload $t9
li $v0, __NR_sigaction
@@ -20,4 +20,4 @@ sigaction:
j $t9
nop
.set reorder
- .end sigaction
+ .end __sigaction
diff --git a/libc/arch-x86/syscalls.mk b/libc/arch-x86/syscalls.mk
index 8683221..5494992 100644
--- a/libc/arch-x86/syscalls.mk
+++ b/libc/arch-x86/syscalls.mk
@@ -22,6 +22,7 @@ syscall_src += arch-x86/syscalls/__rt_sigsuspend.S
syscall_src += arch-x86/syscalls/__rt_sigtimedwait.S
syscall_src += arch-x86/syscalls/__sched_getaffinity.S
syscall_src += arch-x86/syscalls/__set_thread_area.S
+syscall_src += arch-x86/syscalls/__sigaction.S
syscall_src += arch-x86/syscalls/__statfs64.S
syscall_src += arch-x86/syscalls/__sys_clone.S
syscall_src += arch-x86/syscalls/__syslog.S
@@ -179,7 +180,6 @@ syscall_src += arch-x86/syscalls/settimeofday.S
syscall_src += arch-x86/syscalls/setuid.S
syscall_src += arch-x86/syscalls/setxattr.S
syscall_src += arch-x86/syscalls/shutdown.S
-syscall_src += arch-x86/syscalls/sigaction.S
syscall_src += arch-x86/syscalls/sigaltstack.S
syscall_src += arch-x86/syscalls/signalfd4.S
syscall_src += arch-x86/syscalls/socket.S
diff --git a/libc/arch-x86/syscalls/sigaction.S b/libc/arch-x86/syscalls/__sigaction.S
index 015f7f9..d1356a6 100644
--- a/libc/arch-x86/syscalls/sigaction.S
+++ b/libc/arch-x86/syscalls/__sigaction.S
@@ -4,7 +4,7 @@
#include <linux/err.h>
#include <machine/asm.h>
-ENTRY(sigaction)
+ENTRY(__sigaction)
pushl %ebx
pushl %ecx
pushl %edx
@@ -25,4 +25,4 @@ ENTRY(sigaction)
popl %ecx
popl %ebx
ret
-END(sigaction)
+END(__sigaction)
diff --git a/libc/arch-x86_64/x86_64.mk b/libc/arch-x86_64/x86_64.mk
index 13442c7..244eb56 100644
--- a/libc/arch-x86_64/x86_64.mk
+++ b/libc/arch-x86_64/x86_64.mk
@@ -7,7 +7,6 @@ _LIBC_ARCH_COMMON_SRC_FILES := \
arch-x86_64/bionic/_setjmp.S \
arch-x86_64/bionic/setjmp.S \
arch-x86_64/bionic/__set_tls.c \
- arch-x86_64/bionic/sigaction.c \
arch-x86_64/bionic/sigsetjmp.S \
arch-x86_64/bionic/syscall.S \
diff --git a/libc/bionic/sigaction.cpp b/libc/bionic/sigaction.cpp
new file mode 100644
index 0000000..6468b2d
--- /dev/null
+++ b/libc/bionic/sigaction.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 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>
+
+#if __LP64__
+extern "C" void __rt_sigreturn(void);
+extern "C" int __rt_sigaction(int, const struct __kernel_sigaction*, struct __kernel_sigaction*, size_t);
+#else
+extern "C" int __sigaction(int, const struct sigaction*, struct sigaction*);
+#endif
+
+int sigaction(int signal, const struct sigaction* bionic_new_action, struct sigaction* bionic_old_action) {
+#if __LP64__
+ __kernel_sigaction kernel_new_action;
+ if (bionic_new_action != NULL) {
+ kernel_new_action.sa_flags = bionic_new_action->sa_flags;
+ kernel_new_action.sa_handler = bionic_new_action->sa_handler;
+ kernel_new_action.sa_mask = bionic_new_action->sa_mask;
+ kernel_new_action.sa_restorer = bionic_new_action->sa_restorer;
+
+ if (!(kernel_new_action.sa_flags & SA_RESTORER)) {
+ kernel_new_action.sa_flags |= SA_RESTORER;
+ kernel_new_action.sa_restorer = &__rt_sigreturn;
+ }
+ }
+
+ __kernel_sigaction kernel_old_action;
+ int result = __rt_sigaction(signal,
+ (bionic_new_action != NULL) ? &kernel_new_action : NULL,
+ (bionic_old_action != NULL) ? &kernel_old_action : NULL,
+ sizeof(sigset_t));
+
+ if (bionic_old_action != NULL) {
+ bionic_old_action->sa_flags = kernel_old_action.sa_flags;
+ bionic_old_action->sa_handler = kernel_old_action.sa_handler;
+ bionic_old_action->sa_mask = kernel_old_action.sa_mask;
+ bionic_old_action->sa_restorer = kernel_old_action.sa_restorer;
+
+ if (bionic_old_action->sa_restorer == &__rt_sigreturn) {
+ bionic_old_action->sa_flags &= ~SA_RESTORER;
+ }
+ }
+
+ return result;
+#else
+ // The 32-bit ABI is broken. struct sigaction includes a too-small sigset_t.
+ // TODO: if we also had correct struct sigaction definitions available, we could copy in and out.
+ return __sigaction(signal, bionic_new_action, bionic_old_action);
+#endif
+}
diff --git a/libc/arch-x86_64/bionic/sigaction.c b/libc/bionic/sigaddset.cpp
index d5622be..33ec6f8 100644
--- a/libc/arch-x86_64/bionic/sigaction.c
+++ b/libc/bionic/sigaddset.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,25 +28,13 @@
#include <signal.h>
-extern void __rt_sigreturn(void);
-extern int __rt_sigaction(int, const struct sigaction*, struct sigaction*, size_t);
-
-int sigaction(int sig, const struct sigaction* act, struct sigaction* old_act) {
- struct sigaction sa;
-
- if (act != NULL && !(act->sa_flags & SA_RESTORER)) {
- sa = *act;
- act = &sa;
- sa.sa_flags |= SA_RESTORER;
- sa.sa_restorer = &__rt_sigreturn;
+int sigaddset(sigset_t* set, int signum) {
+ int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+ unsigned long* local_set = (unsigned long*) set;
+ if (set == NULL || bit < 0 || bit >= (int) (8*sizeof(sigset_t))) {
+ errno = EINVAL;
+ return -1;
}
-
- int result = __rt_sigaction(sig, act, old_act, sizeof(sigset_t));
-
- if (old_act != NULL && (old_act->sa_restorer == &__rt_sigreturn)) {
- old_act->sa_flags &= ~SA_RESTORER;
- }
-
- return result;
+ local_set[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
+ return 0;
}
-
diff --git a/libc/bionic/sigdelset.cpp b/libc/bionic/sigdelset.cpp
new file mode 100644
index 0000000..9eea250
--- /dev/null
+++ b/libc/bionic/sigdelset.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2008 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 sigdelset(sigset_t* set, int signum) {
+ int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+ unsigned long* local_set = (unsigned long*) set;
+ if (set == NULL || bit < 0 || bit >= (int) (8*sizeof(sigset_t))) {
+ errno = EINVAL;
+ return -1;
+ }
+ local_set[bit / LONG_BIT] &= ~(1UL << (bit % LONG_BIT));
+ return 0;
+}
diff --git a/libc/bionic/sigemptyset.cpp b/libc/bionic/sigemptyset.cpp
new file mode 100644
index 0000000..2993169
--- /dev/null
+++ b/libc/bionic/sigemptyset.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 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 sigemptyset(sigset_t* set) {
+ if (set == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ memset(set, 0, sizeof(sigset_t));
+ return 0;
+}
diff --git a/libc/bionic/sigfillset.cpp b/libc/bionic/sigfillset.cpp
new file mode 100644
index 0000000..7b7cbb8
--- /dev/null
+++ b/libc/bionic/sigfillset.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 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 sigfillset(sigset_t* set) {
+ if (set == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ memset(set, ~0, sizeof(sigset_t));
+ return 0;
+}
diff --git a/libc/bionic/sigismember.cpp b/libc/bionic/sigismember.cpp
new file mode 100644
index 0000000..0dc73ac
--- /dev/null
+++ b/libc/bionic/sigismember.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2008 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 sigismember(const sigset_t* set, int signum) {
+ int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+ const unsigned long* local_set = (const unsigned long*) set;
+ if (set == NULL || bit < 0 || bit >= (int) (8*sizeof(sigset_t))) {
+ errno = EINVAL;
+ return -1;
+ }
+ return (int) ((local_set[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1);
+}
diff --git a/libc/bionic/signal.c b/libc/bionic/signal.cpp
index 949db13..48b2e72 100644
--- a/libc/bionic/signal.c
+++ b/libc/bionic/signal.cpp
@@ -25,33 +25,30 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#include <signal.h>
-
-static __sighandler_t
-_signal(int signum, __sighandler_t handler, int flags)
-{
- struct sigaction sa;
- __sighandler_t result = SIG_ERR;
-
- sigemptyset( &sa.sa_mask );
+#include <signal.h>
- sa.sa_handler = handler;
- sa.sa_flags = flags;
+static sighandler_t _signal(int signum, sighandler_t handler, int flags) {
+ struct sigaction sa;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = handler;
+ sa.sa_flags = flags;
- if ( !sigaction( signum, &sa, &sa ) )
- result = (__sighandler_t) sa.sa_handler;
+ if (sigaction(signum, &sa, &sa) == -1) {
+ return SIG_ERR;
+ }
- return result;
+ return (sighandler_t) sa.sa_handler;
}
-
-__sighandler_t bsd_signal(int signum, __sighandler_t handler)
-{
+sighandler_t bsd_signal(int signum, sighandler_t handler) {
return _signal(signum, handler, SA_RESTART);
}
-__sighandler_t sysv_signal(int signum, __sighandler_t handler)
-{
+sighandler_t sysv_signal(int signum, sighandler_t handler) {
return _signal(signum, handler, SA_RESETHAND);
}
+
+sighandler_t signal(int signum, sighandler_t handler) {
+ return bsd_signal(signum, handler);
+}
diff --git a/libc/include/signal.h b/libc/include/signal.h
index e211ef7..5e74161 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -25,6 +25,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+
#ifndef _SIGNAL_H_
#define _SIGNAL_H_
@@ -33,7 +34,18 @@
#include <limits.h> /* For LONG_BIT */
#include <string.h> /* For memset() */
#include <sys/types.h>
-#include <asm/signal.h>
+
+#if defined(__LP64__)
+/* For 64-bit, the kernel's struct sigaction doesn't match the POSIX one,
+ * so we need to expose our own and translate behind the scenes. */
+# define sigaction __kernel_sigaction
+# include <asm/signal.h>
+# undef sigaction
+#else
+/* For 32-bit, we're stuck with the definitions we already shipped,
+ * even though they contain a sigset_t that's too small. */
+# include <asm/signal.h>
+#endif
#define __ARCH_SI_UID_T __kernel_uid32_t
#include <asm/siginfo.h>
@@ -57,73 +69,37 @@ typedef int sig_atomic_t;
extern const char* const sys_siglist[];
extern const char* const sys_signame[];
-static __inline__ int sigismember(const sigset_t* set, int signum) {
- int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
- const unsigned long* local_set = (const unsigned long*) set;
- if (set == NULL || bit < 0 || bit >= (int) (8*sizeof(sigset_t))) {
- errno = EINVAL;
- return -1;
- }
- return (int) ((local_set[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1);
-}
-
-static __inline__ int sigaddset(sigset_t* set, int signum) {
- int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
- unsigned long* local_set = (unsigned long*) set;
- if (set == NULL || bit < 0 || bit >= (int) (8*sizeof(sigset_t))) {
- errno = EINVAL;
- return -1;
- }
- local_set[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
- return 0;
-}
-
-static __inline__ int sigdelset(sigset_t* set, int signum) {
- int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
- unsigned long* local_set = (unsigned long*) set;
- if (set == NULL || bit < 0 || bit >= (int) (8*sizeof(sigset_t))) {
- errno = EINVAL;
- return -1;
- }
- local_set[bit / LONG_BIT] &= ~(1UL << (bit % LONG_BIT));
- return 0;
-}
-
-static __inline__ int sigemptyset(sigset_t* set) {
- if (set == NULL) {
- errno = EINVAL;
- return -1;
- }
- memset(set, 0, sizeof *set);
- return 0;
-}
-
-static __inline__ int sigfillset(sigset_t* set) {
- if (set == NULL) {
- errno = EINVAL;
- return -1;
- }
- memset(set, ~0, sizeof *set);
- return 0;
-}
-
-
-/* compatibility types */
-typedef void (*sig_t)(int);
-typedef sig_t sighandler_t;
-
-/* differentiater between sysv and bsd behaviour 8*/
-extern __sighandler_t sysv_signal(int, __sighandler_t);
-extern __sighandler_t bsd_signal(int, __sighandler_t);
-
-/* the default is bsd */
-static __inline__ __sighandler_t signal(int s, __sighandler_t f)
-{
- return bsd_signal(s,f);
-}
+typedef __sighandler_t sig_t; /* BSD compatibility. */
+typedef __sighandler_t sighandler_t; /* glibc compatibility. */
+
+#if __LP64__
+
+struct sigaction {
+ unsigned int sa_flags;
+ union {
+ sighandler_t sa_handler;
+ void (*sa_sigaction)(int, struct siginfo*, void*);
+ };
+ sigset_t sa_mask;
+ void (*sa_restorer)(void);
+};
+
+#endif
extern int sigaction(int, const struct sigaction*, struct sigaction*);
+
+extern sighandler_t signal(int, sighandler_t);
+extern sighandler_t bsd_signal(int, sighandler_t);
+extern sighandler_t sysv_signal(int, sighandler_t);
+
extern int siginterrupt(int, int);
+
+extern int sigaddset(sigset_t*, int);
+extern int sigdelset(sigset_t*, int);
+extern int sigemptyset(sigset_t*);
+extern int sigfillset(sigset_t*);
+extern int sigismember(const sigset_t*, int);
+
extern int sigpending(sigset_t*) __nonnull((1));
extern int sigprocmask(int, const sigset_t*, sigset_t*);
extern int sigsuspend(const sigset_t*) __nonnull((1));
@@ -132,6 +108,7 @@ extern int sigwait(const sigset_t*, int*) __nonnull((1, 2));
extern int raise(int);
extern int kill(pid_t, int);
extern int killpg(int, int);
+
extern int sigaltstack(const stack_t*, stack_t*);
extern void psiginfo(const siginfo_t*, const char*);
diff --git a/linker/debugger.cpp b/linker/debugger.cpp
index 6ddd358..c947522 100644
--- a/linker/debugger.cpp
+++ b/linker/debugger.cpp
@@ -176,12 +176,7 @@ static bool have_siginfo(int signum) {
* Catches fatal signals so we can ask debuggerd to ptrace us before
* we crash.
*/
-#if __LP64__ // TODO: implement 64-bit sigaction using rt_sigaction.
-void debuggerd_signal_handler(int n) {
- siginfo_t* info = NULL;
-#else
void debuggerd_signal_handler(int n, siginfo_t* info, void*) {
-#endif
/*
* It's possible somebody cleared the SA_SIGINFO flag, which would mean
* our "info" arg holds an undefined value.
@@ -254,11 +249,7 @@ void debuggerd_init() {
struct sigaction action;
memset(&action, 0, sizeof(action));
sigemptyset(&action.sa_mask);
-#if __LP64__ // TODO: implement 64-bit sigaction using rt_sigaction.
- action.sa_handler = debuggerd_signal_handler;
-#else
action.sa_sigaction = debuggerd_signal_handler;
-#endif
action.sa_flags = SA_RESTART | SA_SIGINFO;
// Use the alternate signal stack if available so we can catch stack overflows.
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 4a7c155..a03232f 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -284,11 +284,13 @@ static void pthread_kill__in_signal_handler_helper(int signal_number) {
TEST(pthread, pthread_kill__in_signal_handler) {
struct sigaction action;
+ struct sigaction original_action;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
action.sa_handler = pthread_kill__in_signal_handler_helper;
- sigaction(SIGALRM, &action, NULL);
+ ASSERT_EQ(0, sigaction(SIGALRM, &action, &original_action));
ASSERT_EQ(0, pthread_kill(pthread_self(), SIGALRM));
+ ASSERT_EQ(0, sigaction(SIGALRM, &original_action, NULL));
}
TEST(pthread, pthread_detach__no_such_thread) {
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index a719fe7..3070747 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -210,3 +210,44 @@ TEST(signal, sigsuspend_sigpending) {
// Restore the original set.
assert(0 == sigprocmask(SIG_SETMASK, &original_set, NULL));
}
+
+static void EmptySignalHandler(int) {}
+static void EmptySignalAction(int, siginfo_t*, void*) {}
+
+TEST(signal, sigaction) {
+ // See what's currently set for SIGALRM.
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa));
+ ASSERT_TRUE(sa.sa_handler == NULL);
+ ASSERT_TRUE(sa.sa_sigaction == NULL);
+ ASSERT_TRUE(sa.sa_flags == 0);
+
+ // Set a traditional sa_handler signal handler.
+ memset(&sa, 0, sizeof(sa));
+ sigaddset(&sa.sa_mask, SIGALRM);
+ sa.sa_flags = SA_ONSTACK;
+ sa.sa_handler = EmptySignalHandler;
+ ASSERT_EQ(0, sigaction(SIGALRM, &sa, NULL));
+
+ // Check that we can read it back.
+ memset(&sa, 0, sizeof(sa));
+ ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa));
+ ASSERT_TRUE(sa.sa_handler == EmptySignalHandler);
+ ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler);
+ ASSERT_TRUE(sa.sa_flags == SA_ONSTACK);
+
+ // Set a new-style sa_sigaction signal handler.
+ memset(&sa, 0, sizeof(sa));
+ sigaddset(&sa.sa_mask, SIGALRM);
+ sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
+ sa.sa_sigaction = EmptySignalAction;
+ ASSERT_EQ(0, sigaction(SIGALRM, &sa, NULL));
+
+ // Check that we can read it back.
+ memset(&sa, 0, sizeof(sa));
+ ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa));
+ ASSERT_TRUE(sa.sa_sigaction == EmptySignalAction);
+ ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler);
+ ASSERT_TRUE(sa.sa_flags == (SA_ONSTACK | SA_SIGINFO));
+}