1 /* Linuxthreads - a simple clone()-based implementation of Posix */
2 /* threads for Linux. */
3 /* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
5 /* This program is free software; you can redistribute it and/or */
6 /* modify it under the terms of the GNU Library General Public License */
7 /* as published by the Free Software Foundation; either version 2 */
8 /* of the License, or (at your option) any later version. */
10 /* This program is distributed in the hope that it will be useful, */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
13 /* GNU Library General Public License for more details. */
15 /* Handling of signals */
20 #include "internals.h"
23 int pthread_sigmask(int how
, const sigset_t
* newmask
, sigset_t
* oldmask
)
27 if (newmask
!= NULL
) {
29 /* Don't allow __pthread_sig_restart to be unmasked.
30 Don't allow __pthread_sig_cancel to be masked. */
33 sigaddset(&mask
, __pthread_sig_restart
);
34 sigdelset(&mask
, __pthread_sig_cancel
);
37 sigdelset(&mask
, __pthread_sig_cancel
);
40 sigdelset(&mask
, __pthread_sig_restart
);
45 if (sigprocmask(how
, newmask
, oldmask
) == -1)
51 int pthread_kill(pthread_t thread
, int signo
)
53 pthread_handle handle
= thread_handle(thread
);
56 __pthread_lock(&handle
->h_lock
, NULL
);
57 if (invalid_handle(handle
, thread
)) {
58 __pthread_unlock(&handle
->h_lock
);
61 pid
= handle
->h_descr
->p_pid
;
62 __pthread_unlock(&handle
->h_lock
);
63 if (kill(pid
, signo
) == -1)
69 /* User-provided signal handlers */
70 static __sighandler_t sighandler
[NSIG
];
72 /* The wrapper around user-provided signal handlers */
73 static void pthread_sighandler(int signo
)
75 pthread_descr self
= thread_self();
77 /* If we're in a sigwait operation, just record the signal received
78 and return without calling the user's handler */
79 if (THREAD_GETMEM(self
, p_sigwaiting
)) {
80 THREAD_SETMEM(self
, p_sigwaiting
, 0);
81 THREAD_SETMEM(self
, p_signal
, signo
);
84 /* Record that we're in a signal handler and call the user's
86 in_sighandler
= THREAD_GETMEM(self
, p_in_sighandler
);
87 if (in_sighandler
== NULL
)
88 THREAD_SETMEM(self
, p_in_sighandler
, CURRENT_STACK_FRAME
);
89 sighandler
[signo
](signo
);
90 if (in_sighandler
== NULL
)
91 THREAD_SETMEM(self
, p_in_sighandler
, NULL
);
94 /* The wrapper around sigaction. Install our own signal handler
96 int sigaction(int sig
, const struct sigaction
* act
,
97 struct sigaction
* oact
)
99 struct sigaction newact
;
100 struct sigaction
*newactp
;
102 if (sig
== __pthread_sig_restart
||
103 sig
== __pthread_sig_cancel
||
104 (sig
== __pthread_sig_debug
&& __pthread_sig_debug
> 0))
109 if (act
->sa_handler
!= SIG_IGN
&& act
->sa_handler
!= SIG_DFL
110 && sig
> 0 && sig
< NSIG
)
111 newact
.sa_handler
= pthread_sighandler
;
116 if (__sigaction(sig
, newactp
, oact
) == -1)
118 if (sig
> 0 && sig
< NSIG
)
121 oact
->sa_handler
= sighandler
[sig
];
123 sighandler
[sig
] = act
->sa_handler
;
128 /* A signal handler that does nothing */
129 static void pthread_null_sighandler(int sig
) { }
131 /* sigwait -- synchronously wait for a signal */
132 int sigwait(const sigset_t
* set
, int * sig
)
134 volatile pthread_descr self
= thread_self();
140 /* Get ready to block all signals except those in set
141 and the cancellation signal.
142 Also check that handlers are installed on all signals in set,
143 and if not, install our dummy handler. This is conformant to
144 POSIX: "The effect of sigwait() on the signal actions for the
145 signals in set is unspecified." */
147 sigdelset(&mask
, __pthread_sig_cancel
);
148 for (s
= 1; s
<= NSIG
; s
++) {
149 if (sigismember(set
, s
) &&
150 s
!= __pthread_sig_restart
&&
151 s
!= __pthread_sig_cancel
&&
152 s
!= __pthread_sig_debug
) {
154 if (sighandler
[s
] == NULL
||
155 sighandler
[s
] == SIG_DFL
||
156 sighandler
[s
] == SIG_IGN
) {
157 sa
.sa_handler
= pthread_null_sighandler
;
158 sigemptyset(&sa
.sa_mask
);
160 sigaction(s
, &sa
, NULL
);
164 /* Test for cancellation */
165 if (sigsetjmp(jmpbuf
, 1) == 0) {
166 THREAD_SETMEM(self
, p_cancel_jmp
, &jmpbuf
);
167 if (! (THREAD_GETMEM(self
, p_canceled
)
168 && THREAD_GETMEM(self
, p_cancelstate
) == PTHREAD_CANCEL_ENABLE
)) {
169 /* Reset the signal count */
170 THREAD_SETMEM(self
, p_signal
, 0);
171 /* Say we're in sigwait */
172 THREAD_SETMEM(self
, p_sigwaiting
, 1);
173 /* Unblock the signals and wait for them */
177 THREAD_SETMEM(self
, p_cancel_jmp
, NULL
);
178 /* The signals are now reblocked. Check for cancellation */
179 pthread_testcancel();
180 /* We should have self->p_signal != 0 and equal to the signal received */
181 *sig
= THREAD_GETMEM(self
, p_signal
);
185 /* Redefine raise() to send signal to calling thread only,
186 as per POSIX 1003.1c */
189 int retcode
= pthread_kill(pthread_self(), sig
);