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