summaryrefslogtreecommitdiff
path: root/linuxthreads/signals.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1999-01-07 11:53:05 +0000
committerUlrich Drepper <drepper@redhat.com>1999-01-07 11:53:05 +0000
commitb92ad8d61f18a3e9a61434e2e3252efd862bd7f4 (patch)
treea673f7750cb17ce2adaee14e9a8b4855447b6feb /linuxthreads/signals.c
parent34992338178abc47897f10ce4fb12d204e682b14 (diff)
downloadglibc-b92ad8d61f18a3e9a61434e2e3252efd862bd7f4.tar.gz
1999-01-07 Xavier Leroy <Xavier.Leroy@inria.fr>
* pthread.c: Use a third signal __pthread_sig_debug distinct from __pthread_sig_cancel to notify gdb when a thread is created * manager.c: Likewise. * internals.h: Likewise. * signals.c: The implementation of sigwait(s) assumed that all signals in s have signal handlers already attached. This is not required by the standard, so make it work also if some of the signals have no handlers.
Diffstat (limited to 'linuxthreads/signals.c')
-rw-r--r--linuxthreads/signals.c37
1 files changed, 32 insertions, 5 deletions
diff --git a/linuxthreads/signals.c b/linuxthreads/signals.c
index e833778d53..a352eb951d 100644
--- a/linuxthreads/signals.c
+++ b/linuxthreads/signals.c
@@ -91,19 +91,23 @@ static void pthread_sighandler(int signo)
THREAD_SETMEM(self, p_in_sighandler, NULL);
}
+/* The wrapper around sigaction. Install our own signal handler
+ around the signal. */
int sigaction(int sig, const struct sigaction * act,
struct sigaction * oact)
{
struct sigaction newact;
struct sigaction *newactp;
- if (sig == __pthread_sig_restart || sig == __pthread_sig_cancel)
+ if (sig == __pthread_sig_restart ||
+ sig == __pthread_sig_cancel ||
+ (sig == __pthread_sig_debug && __pthread_sig_debug > 0))
return EINVAL;
if (act)
{
newact = *act;
if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL
- && sig < NSIG)
+ && sig > 0 && sig < NSIG)
newact.sa_handler = pthread_sighandler;
newactp = &newact;
}
@@ -111,7 +115,7 @@ int sigaction(int sig, const struct sigaction * act,
newactp = NULL;
if (__sigaction(sig, newactp, oact) == -1)
return -1;
- if (sig < NSIG)
+ if (sig > 0 && sig < NSIG)
{
if (oact != NULL)
oact->sa_handler = sighandler[sig];
@@ -121,20 +125,41 @@ int sigaction(int sig, const struct sigaction * act,
return 0;
}
+/* A signal handler that does nothing */
+static void pthread_null_sighandler(int sig) { }
+
+/* sigwait -- synchronously wait for a signal */
int sigwait(const sigset_t * set, int * sig)
{
volatile pthread_descr self = thread_self();
sigset_t mask;
int s;
sigjmp_buf jmpbuf;
+ struct sigaction sa;
/* Get ready to block all signals except those in set
- and the cancellation signal */
+ and the cancellation signal.
+ Also check that handlers are installed on all signals in set,
+ and if not, install our dummy handler. This is conformant to
+ POSIX: "The effect of sigwait() on the signal actions for the
+ signals in set is unspecified." */
sigfillset(&mask);
sigdelset(&mask, __pthread_sig_cancel);
for (s = 1; s <= NSIG; s++) {
- if (sigismember(set, s) && s != __pthread_sig_cancel)
+ if (sigismember(set, s) &&
+ s != __pthread_sig_restart &&
+ s != __pthread_sig_cancel &&
+ s != __pthread_sig_debug) {
sigdelset(&mask, s);
+ if (sighandler[s] == NULL ||
+ sighandler[s] == SIG_DFL ||
+ sighandler[s] == SIG_IGN) {
+ sa.sa_handler = pthread_null_sighandler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sigaction(s, &sa, NULL);
+ }
+ }
}
/* Test for cancellation */
if (sigsetjmp(jmpbuf, 1) == 0) {
@@ -157,6 +182,8 @@ int sigwait(const sigset_t * set, int * sig)
return 0;
}
+/* Redefine raise() to send signal to calling thread only,
+ as per POSIX 1003.1c */
int raise (int sig)
{
int retcode = pthread_kill(pthread_self(), sig);