diff options
Diffstat (limited to 'libpthread/linuxthreads')
-rw-r--r-- | libpthread/linuxthreads/signals.c | 67 |
1 files changed, 38 insertions, 29 deletions
diff --git a/libpthread/linuxthreads/signals.c b/libpthread/linuxthreads/signals.c index 0174ec41c..90beaae9b 100644 --- a/libpthread/linuxthreads/signals.c +++ b/libpthread/linuxthreads/signals.c @@ -21,6 +21,7 @@ #include "internals.h" #include "spinlock.h" #include <ucontext.h> +#include "debug.h" #include <bits/sigcontextinfo.h> /* mods for uClibc: __libc_sigaction is not in any standard headers */ @@ -76,15 +77,11 @@ int pthread_kill(pthread_t thread, int signo) return 0; } -/* User-provided signal handlers */ -static union -{ - arch_sighandler_t old; - void (*rt) (int, struct siginfo *, struct ucontext *); -} sighandler[NSIG]; +union sighandler __sighandler[NSIG] = + { [1 ... NSIG - 1] = { (arch_sighandler_t) SIG_ERR } }; /* The wrapper around user-provided signal handlers */ -static void pthread_sighandler(int signo, SIGCONTEXT ctx) +static void __pthread_sighandler(int signo, SIGCONTEXT ctx) { pthread_descr self = thread_self(); char * in_sighandler; @@ -100,13 +97,13 @@ static void pthread_sighandler(int signo, SIGCONTEXT ctx) in_sighandler = THREAD_GETMEM(self, p_in_sighandler); if (in_sighandler == NULL) THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME); - sighandler[signo].old(signo, SIGCONTEXT_EXTRA_ARGS ctx); + __sighandler[signo].old(signo, SIGCONTEXT_EXTRA_ARGS ctx); if (in_sighandler == NULL) THREAD_SETMEM(self, p_in_sighandler, NULL); } /* The same, this time for real-time signals. */ -static void pthread_sighandler_rt(int signo, struct siginfo *si, +static void __pthread_sighandler_rt(int signo, struct siginfo *si, struct ucontext *uc) { pthread_descr self = thread_self(); @@ -123,7 +120,7 @@ static void pthread_sighandler_rt(int signo, struct siginfo *si, in_sighandler = THREAD_GETMEM(self, p_in_sighandler); if (in_sighandler == NULL) THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME); - sighandler[signo].rt(signo, si, uc); + __sighandler[signo].rt(signo, si, uc); if (in_sighandler == NULL) THREAD_SETMEM(self, p_in_sighandler, NULL); } @@ -135,14 +132,18 @@ int __sigaction(int sig, const struct sigaction * act, { struct sigaction newact; struct sigaction *newactp; + __sighandler_t old = SIG_DFL; -#ifdef DEBUG_PT -printf(__FUNCTION__": pthreads wrapper!\n"); -#endif + PDEBUG("pthreads wrapper!\n"); if (sig == __pthread_sig_restart || sig == __pthread_sig_cancel || (sig == __pthread_sig_debug && __pthread_sig_debug > 0)) - return EINVAL; + { + __set_errno (EINVAL); + return -1; + } + if (sig > 0 && sig < NSIG) + old = (__sighandler_t) __sighandler[sig].old; if (act) { newact = *act; @@ -150,27 +151,35 @@ printf(__FUNCTION__": pthreads wrapper!\n"); && sig > 0 && sig < NSIG) { if (act->sa_flags & SA_SIGINFO) - newact.sa_handler = (__sighandler_t) pthread_sighandler_rt; + newact.sa_handler = (__sighandler_t) __pthread_sighandler_rt; else - newact.sa_handler = (__sighandler_t) pthread_sighandler; + newact.sa_handler = (__sighandler_t) __pthread_sighandler; + if (old == SIG_IGN || old == SIG_DFL || old == SIG_ERR) + __sighandler[sig].old = (arch_sighandler_t) act->sa_handler; } newactp = &newact; } else newactp = NULL; if (__libc_sigaction(sig, newactp, oact) == -1) - return -1; -#ifdef DEBUG_PT -printf(__FUNCTION__": signahdler installed, __sigaction successful\n"); -#endif + { + if (act) + __sighandler[sig].old = (arch_sighandler_t) old; + return -1; + } + PDEBUG("signahdler installed, __sigaction successful\n"); if (sig > 0 && sig < NSIG) { - if (oact != NULL) - oact->sa_handler = (__sighandler_t) sighandler[sig].old; + if (oact != NULL + /* We may have inherited SIG_IGN from the parent, so return the + kernel's idea of the signal handler the first time + through. */ + && old != SIG_ERR) + oact->sa_handler = old; if (act) - /* For the assignment is does not matter whether it's a normal + /* For the assignment it does not matter whether it's a normal or real-time signal. */ - sighandler[sig].old = (arch_sighandler_t) act->sa_handler; + __sighandler[sig].old = (arch_sighandler_t) act->sa_handler; } return 0; } @@ -196,17 +205,17 @@ int sigwait(const sigset_t * set, int * sig) signals in set is unspecified." */ sigfillset(&mask); sigdelset(&mask, __pthread_sig_cancel); - for (s = 1; s <= NSIG; s++) { + for (s = 1; s < NSIG; s++) { if (sigismember(set, s) && s != __pthread_sig_restart && s != __pthread_sig_cancel && s != __pthread_sig_debug) { sigdelset(&mask, s); - if (sighandler[s].old == NULL || - sighandler[s].old == (arch_sighandler_t) SIG_DFL || - sighandler[s].old == (arch_sighandler_t) SIG_IGN) { + if (__sighandler[s].old == (arch_sighandler_t) SIG_ERR || + __sighandler[s].old == (arch_sighandler_t) SIG_DFL || + __sighandler[s].old == (arch_sighandler_t) SIG_IGN) { sa.sa_handler = pthread_null_sighandler; - sigemptyset(&sa.sa_mask); + sigfillset(&sa.sa_mask); sa.sa_flags = 0; sigaction(s, &sa, NULL); } |