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"
25 int pthread_sigmask(int how
, const sigset_t
* newmask
, sigset_t
* oldmask
)
29 if (newmask
!= NULL
) {
31 /* Don't allow __pthread_sig_restart to be unmasked.
32 Don't allow __pthread_sig_cancel to be masked. */
35 sigaddset(&mask
, __pthread_sig_restart
);
36 sigdelset(&mask
, __pthread_sig_cancel
);
39 sigdelset(&mask
, __pthread_sig_cancel
);
42 sigdelset(&mask
, __pthread_sig_restart
);
47 if (sigprocmask(how
, newmask
, oldmask
) == -1)
53 int pthread_kill(pthread_t thread
, int signo
)
55 pthread_handle handle
= thread_handle(thread
);
58 __pthread_lock(&handle
->h_lock
, NULL
);
59 if (invalid_handle(handle
, thread
)) {
60 __pthread_unlock(&handle
->h_lock
);
63 pid
= handle
->h_descr
->p_pid
;
64 __pthread_unlock(&handle
->h_lock
);
65 if (kill(pid
, signo
) == -1)
71 union sighandler __sighandler
[NSIG
] =
72 { [1 ... NSIG
- 1] = { (arch_sighandler_t
) SIG_ERR
} };
74 /* The wrapper around sigaction. Install our own signal handler
76 int __pthread_sigaction(int sig
, const struct sigaction
* act
,
77 struct sigaction
* oact
)
79 struct sigaction newact
;
80 struct sigaction
*newactp
;
81 __sighandler_t old
= SIG_DFL
;
83 if (sig
== __pthread_sig_restart
||
84 sig
== __pthread_sig_cancel
||
85 (sig
== __pthread_sig_debug
&& __pthread_sig_debug
> 0))
90 if (sig
> 0 && sig
< NSIG
)
91 old
= (__sighandler_t
) __sighandler
[sig
].old
;
95 if (act
->sa_handler
!= SIG_IGN
&& act
->sa_handler
!= SIG_DFL
96 && sig
> 0 && sig
< NSIG
)
98 if (act
->sa_flags
& SA_SIGINFO
)
99 newact
.sa_handler
= (__sighandler_t
) __pthread_sighandler_rt
;
101 newact
.sa_handler
= (__sighandler_t
) __pthread_sighandler
;
102 if (old
== SIG_IGN
|| old
== SIG_DFL
|| old
== SIG_ERR
)
103 __sighandler
[sig
].old
= (arch_sighandler_t
) act
->sa_handler
;
109 if (__libc_sigaction(sig
, newactp
, oact
) == -1)
112 __sighandler
[sig
].old
= (arch_sighandler_t
) old
;
115 if (sig
> 0 && sig
< NSIG
)
118 /* We may have inherited SIG_IGN from the parent, so return the
119 kernel's idea of the signal handler the first time
122 oact
->sa_handler
= old
;
124 /* For the assignment it does not matter whether it's a normal
125 or real-time signal. */
126 __sighandler
[sig
].old
= (arch_sighandler_t
) act
->sa_handler
;
131 strong_alias(__pthread_sigaction
, __sigaction
)
132 strong_alias(__pthread_sigaction
, sigaction
)
135 /* sigwait -- synchronously wait for a signal */
136 int __pthread_sigwait(const sigset_t
* set
, int * sig
)
138 volatile pthread_descr self
= thread_self();
144 /* Get ready to block all signals except those in set
145 and the cancellation signal.
146 Also check that handlers are installed on all signals in set,
147 and if not, install our dummy handler. This is conformant to
148 POSIX: "The effect of sigwait() on the signal actions for the
149 signals in set is unspecified." */
151 sigdelset(&mask
, __pthread_sig_cancel
);
152 for (s
= 1; s
< NSIG
; s
++) {
153 if (sigismember(set
, s
) &&
154 s
!= __pthread_sig_restart
&&
155 s
!= __pthread_sig_cancel
&&
156 s
!= __pthread_sig_debug
) {
158 if (__sighandler
[s
].old
== (arch_sighandler_t
) SIG_ERR
||
159 __sighandler
[s
].old
== (arch_sighandler_t
) SIG_DFL
||
160 __sighandler
[s
].old
== (arch_sighandler_t
) SIG_IGN
) {
161 sa
.sa_handler
= __pthread_null_sighandler
;
162 sigfillset(&sa
.sa_mask
);
164 sigaction(s
, &sa
, NULL
);
168 /* Test for cancellation */
169 if (sigsetjmp(jmpbuf
, 1) == 0) {
170 THREAD_SETMEM(self
, p_cancel_jmp
, &jmpbuf
);
171 if (! (THREAD_GETMEM(self
, p_canceled
)
172 && THREAD_GETMEM(self
, p_cancelstate
) == PTHREAD_CANCEL_ENABLE
)) {
173 /* Reset the signal count */
174 THREAD_SETMEM(self
, p_signal
, 0);
175 /* Say we're in sigwait */
176 THREAD_SETMEM(self
, p_sigwaiting
, 1);
177 /* Unblock the signals and wait for them */
181 THREAD_SETMEM(self
, p_cancel_jmp
, NULL
);
182 /* The signals are now reblocked. Check for cancellation */
183 pthread_testcancel();
184 /* We should have self->p_signal != 0 and equal to the signal received */
185 *sig
= THREAD_GETMEM(self
, p_signal
);
189 strong_alias (__pthread_sigwait
, sigwait
)
192 /* Redefine raise() to send signal to calling thread only,
193 as per POSIX 1003.1c */
194 int __pthread_raise (int sig
)
196 int retcode
= pthread_kill(pthread_self(), sig
);
205 strong_alias (__pthread_raise
, raise
)
208 /* This files handles cancellation internally. */
209 LIBC_CANCEL_HANDLED ();