Merge "Fix sigaction(3) for 64-bit."
This commit is contained in:
commit
967cd1bcaf
20 changed files with 358 additions and 126 deletions
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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)
|
|
@ -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 \
|
||||
|
||||
|
|
76
libc/bionic/sigaction.cpp
Normal file
76
libc/bionic/sigaction.cpp
Normal 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
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
40
libc/bionic/sigdelset.cpp
Normal file
40
libc/bionic/sigdelset.cpp
Normal 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;
|
||||
}
|
38
libc/bionic/sigemptyset.cpp
Normal file
38
libc/bionic/sigemptyset.cpp
Normal 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;
|
||||
}
|
38
libc/bionic/sigfillset.cpp
Normal file
38
libc/bionic/sigfillset.cpp
Normal 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;
|
||||
}
|
39
libc/bionic/sigismember.cpp
Normal file
39
libc/bionic/sigismember.cpp
Normal 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);
|
||||
}
|
|
@ -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;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_handler = handler;
|
||||
sa.sa_flags = flags;
|
||||
|
||||
static __sighandler_t
|
||||
_signal(int signum, __sighandler_t handler, int flags)
|
||||
{
|
||||
struct sigaction sa;
|
||||
__sighandler_t result = SIG_ERR;
|
||||
if (sigaction(signum, &sa, &sa) == -1) {
|
||||
return SIG_ERR;
|
||||
}
|
||||
|
||||
sigemptyset( &sa.sa_mask );
|
||||
|
||||
sa.sa_handler = handler;
|
||||
sa.sa_flags = flags;
|
||||
|
||||
if ( !sigaction( signum, &sa, &sa ) )
|
||||
result = (__sighandler_t) sa.sa_handler;
|
||||
|
||||
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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
typedef __sighandler_t sig_t; /* BSD compatibility. */
|
||||
typedef __sighandler_t sighandler_t; /* glibc compatibility. */
|
||||
|
||||
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;
|
||||
}
|
||||
#if __LP64__
|
||||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
#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*);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue