Merge "Fix sigaction(3) for 64-bit."

This commit is contained in:
Elliott Hughes 2013-10-17 18:38:31 +00:00 committed by Gerrit Code Review
commit 967cd1bcaf
20 changed files with 358 additions and 126 deletions

View file

@ -125,7 +125,6 @@ libc_common_src_files := \
bionic/sigblock.c \ bionic/sigblock.c \
bionic/siginterrupt.c \ bionic/siginterrupt.c \
bionic/siglist.c \ bionic/siglist.c \
bionic/signal.c \
bionic/signame.c \ bionic/signame.c \
bionic/sigsetmask.c \ bionic/sigsetmask.c \
bionic/sleep.c \ bionic/sleep.c \
@ -246,6 +245,13 @@ libc_bionic_src_files := \
bionic/seteuid.cpp \ bionic/seteuid.cpp \
bionic/setlocale.cpp \ bionic/setlocale.cpp \
bionic/signalfd.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/sigpending.cpp \
bionic/sigprocmask.cpp \ bionic/sigprocmask.cpp \
bionic/sigsuspend.cpp \ bionic/sigsuspend.cpp \

View file

@ -224,7 +224,7 @@ int timerfd_settime(int, int, const struct itimerspec*, struct itimers
int timerfd_gettime(int, struct itimerspec*) all int timerfd_gettime(int, struct itimerspec*) all
# signals # 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_sigaction:rt_sigaction(int, const struct sigaction*, struct sigaction*, size_t) all
int __rt_sigpending:rt_sigpending(sigset_t*, 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 int __rt_sigprocmask:rt_sigprocmask(int, const sigset_t*, sigset_t*, size_t) all

View file

@ -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/__rt_sigtimedwait.S
syscall_src += arch-arm/syscalls/__sched_getaffinity.S syscall_src += arch-arm/syscalls/__sched_getaffinity.S
syscall_src += arch-arm/syscalls/__set_tls.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/__statfs64.S
syscall_src += arch-arm/syscalls/__sys_clone.S syscall_src += arch-arm/syscalls/__sys_clone.S
syscall_src += arch-arm/syscalls/__syslog.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/setuid.S
syscall_src += arch-arm/syscalls/setxattr.S syscall_src += arch-arm/syscalls/setxattr.S
syscall_src += arch-arm/syscalls/shutdown.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/sigaltstack.S
syscall_src += arch-arm/syscalls/signalfd4.S syscall_src += arch-arm/syscalls/signalfd4.S
syscall_src += arch-arm/syscalls/socket.S syscall_src += arch-arm/syscalls/socket.S

View file

@ -4,7 +4,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <machine/asm.h> #include <machine/asm.h>
ENTRY(sigaction) ENTRY(__sigaction)
mov ip, r7 mov ip, r7
ldr r7, =__NR_sigaction ldr r7, =__NR_sigaction
swi #0 swi #0
@ -13,4 +13,4 @@ ENTRY(sigaction)
bxls lr bxls lr
neg r0, r0 neg r0, r0
b __set_errno b __set_errno
END(sigaction) END(__sigaction)

View file

@ -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/__rt_sigtimedwait.S
syscall_src += arch-mips/syscalls/__sched_getaffinity.S syscall_src += arch-mips/syscalls/__sched_getaffinity.S
syscall_src += arch-mips/syscalls/__set_thread_area.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/__statfs64.S
syscall_src += arch-mips/syscalls/__sys_clone.S syscall_src += arch-mips/syscalls/__sys_clone.S
syscall_src += arch-mips/syscalls/__syslog.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/setuid.S
syscall_src += arch-mips/syscalls/setxattr.S syscall_src += arch-mips/syscalls/setxattr.S
syscall_src += arch-mips/syscalls/shutdown.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/sigaltstack.S
syscall_src += arch-mips/syscalls/signalfd4.S syscall_src += arch-mips/syscalls/signalfd4.S
syscall_src += arch-mips/syscalls/socket.S syscall_src += arch-mips/syscalls/socket.S

View file

@ -2,11 +2,11 @@
#include <asm/unistd.h> #include <asm/unistd.h>
.text .text
.globl sigaction .globl __sigaction
.align 4 .align 4
.ent sigaction .ent __sigaction
sigaction: __sigaction:
.set noreorder .set noreorder
.cpload $t9 .cpload $t9
li $v0, __NR_sigaction li $v0, __NR_sigaction
@ -20,4 +20,4 @@ sigaction:
j $t9 j $t9
nop nop
.set reorder .set reorder
.end sigaction .end __sigaction

View file

@ -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/__rt_sigtimedwait.S
syscall_src += arch-x86/syscalls/__sched_getaffinity.S syscall_src += arch-x86/syscalls/__sched_getaffinity.S
syscall_src += arch-x86/syscalls/__set_thread_area.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/__statfs64.S
syscall_src += arch-x86/syscalls/__sys_clone.S syscall_src += arch-x86/syscalls/__sys_clone.S
syscall_src += arch-x86/syscalls/__syslog.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/setuid.S
syscall_src += arch-x86/syscalls/setxattr.S syscall_src += arch-x86/syscalls/setxattr.S
syscall_src += arch-x86/syscalls/shutdown.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/sigaltstack.S
syscall_src += arch-x86/syscalls/signalfd4.S syscall_src += arch-x86/syscalls/signalfd4.S
syscall_src += arch-x86/syscalls/socket.S syscall_src += arch-x86/syscalls/socket.S

View file

@ -4,7 +4,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <machine/asm.h> #include <machine/asm.h>
ENTRY(sigaction) ENTRY(__sigaction)
pushl %ebx pushl %ebx
pushl %ecx pushl %ecx
pushl %edx pushl %edx
@ -25,4 +25,4 @@ ENTRY(sigaction)
popl %ecx popl %ecx
popl %ebx popl %ebx
ret ret
END(sigaction) END(__sigaction)

View file

@ -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/setjmp.S \ arch-x86_64/bionic/setjmp.S \
arch-x86_64/bionic/__set_tls.c \ arch-x86_64/bionic/__set_tls.c \
arch-x86_64/bionic/sigaction.c \
arch-x86_64/bionic/sigsetjmp.S \ arch-x86_64/bionic/sigsetjmp.S \
arch-x86_64/bionic/syscall.S \ arch-x86_64/bionic/syscall.S \

76
libc/bionic/sigaction.cpp Normal file
View file

@ -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
}

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -28,25 +28,13 @@
#include <signal.h> #include <signal.h>
extern void __rt_sigreturn(void); int sigaddset(sigset_t* set, int signum) {
extern int __rt_sigaction(int, const struct sigaction*, struct sigaction*, size_t); int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
unsigned long* local_set = (unsigned long*) set;
int sigaction(int sig, const struct sigaction* act, struct sigaction* old_act) { if (set == NULL || bit < 0 || bit >= (int) (8*sizeof(sigset_t))) {
struct sigaction sa; errno = EINVAL;
return -1;
if (act != NULL && !(act->sa_flags & SA_RESTORER)) {
sa = *act;
act = &sa;
sa.sa_flags |= SA_RESTORER;
sa.sa_restorer = &__rt_sigreturn;
} }
local_set[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
int result = __rt_sigaction(sig, act, old_act, sizeof(sigset_t)); return 0;
if (old_act != NULL && (old_act->sa_restorer == &__rt_sigreturn)) {
old_act->sa_flags &= ~SA_RESTORER;
}
return result;
} }

40
libc/bionic/sigdelset.cpp Normal file
View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -25,33 +25,30 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#include <signal.h> #include <signal.h>
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;
static __sighandler_t if (sigaction(signum, &sa, &sa) == -1) {
_signal(int signum, __sighandler_t handler, int flags) return SIG_ERR;
{ }
struct sigaction sa;
__sighandler_t result = SIG_ERR;
sigemptyset( &sa.sa_mask ); return (sighandler_t) sa.sa_handler;
sa.sa_handler = handler;
sa.sa_flags = flags;
if ( !sigaction( signum, &sa, &sa ) )
result = (__sighandler_t) sa.sa_handler;
return result;
} }
sighandler_t bsd_signal(int signum, sighandler_t handler) {
__sighandler_t bsd_signal(int signum, __sighandler_t handler)
{
return _signal(signum, handler, SA_RESTART); 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); return _signal(signum, handler, SA_RESETHAND);
} }
sighandler_t signal(int signum, sighandler_t handler) {
return bsd_signal(signum, handler);
}

View file

@ -25,6 +25,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#ifndef _SIGNAL_H_ #ifndef _SIGNAL_H_
#define _SIGNAL_H_ #define _SIGNAL_H_
@ -33,7 +34,18 @@
#include <limits.h> /* For LONG_BIT */ #include <limits.h> /* For LONG_BIT */
#include <string.h> /* For memset() */ #include <string.h> /* For memset() */
#include <sys/types.h> #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 #define __ARCH_SI_UID_T __kernel_uid32_t
#include <asm/siginfo.h> #include <asm/siginfo.h>
@ -57,73 +69,37 @@ typedef int sig_atomic_t;
extern const char* const sys_siglist[]; extern const char* const sys_siglist[];
extern const char* const sys_signame[]; extern const char* const sys_signame[];
static __inline__ int sigismember(const sigset_t* set, int signum) { typedef __sighandler_t sig_t; /* BSD compatibility. */
int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0. typedef __sighandler_t sighandler_t; /* glibc compatibility. */
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) { #if __LP64__
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) { struct sigaction {
int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0. unsigned int sa_flags;
unsigned long* local_set = (unsigned long*) set; union {
if (set == NULL || bit < 0 || bit >= (int) (8*sizeof(sigset_t))) { sighandler_t sa_handler;
errno = EINVAL; void (*sa_sigaction)(int, struct siginfo*, void*);
return -1; };
} sigset_t sa_mask;
local_set[bit / LONG_BIT] &= ~(1UL << (bit % LONG_BIT)); void (*sa_restorer)(void);
return 0; };
}
static __inline__ int sigemptyset(sigset_t* set) { #endif
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);
}
extern int sigaction(int, const struct sigaction*, struct sigaction*); 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 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 sigpending(sigset_t*) __nonnull((1));
extern int sigprocmask(int, const sigset_t*, sigset_t*); extern int sigprocmask(int, const sigset_t*, sigset_t*);
extern int sigsuspend(const sigset_t*) __nonnull((1)); 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 raise(int);
extern int kill(pid_t, int); extern int kill(pid_t, int);
extern int killpg(int, int); extern int killpg(int, int);
extern int sigaltstack(const stack_t*, stack_t*); extern int sigaltstack(const stack_t*, stack_t*);
extern void psiginfo(const siginfo_t*, const char*); extern void psiginfo(const siginfo_t*, const char*);

View file

@ -176,12 +176,7 @@ static bool have_siginfo(int signum) {
* Catches fatal signals so we can ask debuggerd to ptrace us before * Catches fatal signals so we can ask debuggerd to ptrace us before
* we crash. * 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*) { void debuggerd_signal_handler(int n, siginfo_t* info, void*) {
#endif
/* /*
* It's possible somebody cleared the SA_SIGINFO flag, which would mean * It's possible somebody cleared the SA_SIGINFO flag, which would mean
* our "info" arg holds an undefined value. * our "info" arg holds an undefined value.
@ -254,11 +249,7 @@ void debuggerd_init() {
struct sigaction action; struct sigaction action;
memset(&action, 0, sizeof(action)); memset(&action, 0, sizeof(action));
sigemptyset(&action.sa_mask); 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; action.sa_sigaction = debuggerd_signal_handler;
#endif
action.sa_flags = SA_RESTART | SA_SIGINFO; action.sa_flags = SA_RESTART | SA_SIGINFO;
// Use the alternate signal stack if available so we can catch stack overflows. // Use the alternate signal stack if available so we can catch stack overflows.

View file

@ -284,11 +284,13 @@ static void pthread_kill__in_signal_handler_helper(int signal_number) {
TEST(pthread, pthread_kill__in_signal_handler) { TEST(pthread, pthread_kill__in_signal_handler) {
struct sigaction action; struct sigaction action;
struct sigaction original_action;
sigemptyset(&action.sa_mask); sigemptyset(&action.sa_mask);
action.sa_flags = 0; action.sa_flags = 0;
action.sa_handler = pthread_kill__in_signal_handler_helper; 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, pthread_kill(pthread_self(), SIGALRM));
ASSERT_EQ(0, sigaction(SIGALRM, &original_action, NULL));
} }
TEST(pthread, pthread_detach__no_such_thread) { TEST(pthread, pthread_detach__no_such_thread) {

View file

@ -210,3 +210,44 @@ TEST(signal, sigsuspend_sigpending) {
// Restore the original set. // Restore the original set.
assert(0 == sigprocmask(SIG_SETMASK, &original_set, NULL)); 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));
}