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 int sigaction(int sig
, const struct sigaction
* act
,
95 struct sigaction
* oact
)
97 struct sigaction newact
;
98 struct sigaction
*newactp
;
100 if (sig
== __pthread_sig_restart
|| sig
== __pthread_sig_cancel
)
105 if (act
->sa_handler
!= SIG_IGN
&& act
->sa_handler
!= SIG_DFL
107 newact
.sa_handler
= pthread_sighandler
;
112 if (__sigaction(sig
, newactp
, oact
) == -1)
117 oact
->sa_handler
= sighandler
[sig
];
119 sighandler
[sig
] = act
->sa_handler
;
124 int sigwait(const sigset_t
* set
, int * sig
)
126 volatile pthread_descr self
= thread_self();
131 /* Get ready to block all signals except those in set
132 and the cancellation signal */
134 sigdelset(&mask
, __pthread_sig_cancel
);
135 for (s
= 1; s
<= NSIG
; s
++) {
136 if (sigismember(set
, s
) && s
!= __pthread_sig_cancel
)
139 /* Test for cancellation */
140 if (sigsetjmp(jmpbuf
, 1) == 0) {
141 THREAD_SETMEM(self
, p_cancel_jmp
, &jmpbuf
);
142 if (! (THREAD_GETMEM(self
, p_canceled
)
143 && THREAD_GETMEM(self
, p_cancelstate
) == PTHREAD_CANCEL_ENABLE
)) {
144 /* Reset the signal count */
145 THREAD_SETMEM(self
, p_signal
, 0);
146 /* Say we're in sigwait */
147 THREAD_SETMEM(self
, p_sigwaiting
, 1);
148 /* Unblock the signals and wait for them */
152 THREAD_SETMEM(self
, p_cancel_jmp
, NULL
);
153 /* The signals are now reblocked. Check for cancellation */
154 pthread_testcancel();
155 /* We should have self->p_signal != 0 and equal to the signal received */
156 *sig
= THREAD_GETMEM(self
, p_signal
);
162 int retcode
= pthread_kill(pthread_self(), sig
);