]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libkse/thread/thr_sig.c
This commit was generated by cvs2svn to compensate for changes in r128212,
[FreeBSD/FreeBSD.git] / lib / libkse / thread / thr_sig.c
1 /*
2  * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by John Birrell.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $FreeBSD$
33  */
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/signalvar.h>
37 #include <signal.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <unistd.h>
41 #include <string.h>
42 #include <pthread.h>
43 #include "thr_private.h"
44
45 /* Prototypes: */
46 static void     build_siginfo(siginfo_t *info, int signo);
47 #ifndef SYSTEM_SCOPE_ONLY
48 static struct pthread *thr_sig_find(struct kse *curkse, int sig,
49                     siginfo_t *info);
50 static void     handle_special_signals(struct kse *curkse, int sig);
51 #endif
52 static void     thr_sigframe_add(struct pthread *thread);
53 static void     thr_sigframe_restore(struct pthread *thread,
54                     struct pthread_sigframe *psf);
55 static void     thr_sigframe_save(struct pthread *thread,
56                     struct pthread_sigframe *psf);
57
58 #define SA_KILL         0x01            /* terminates process by default */
59 #define SA_STOP         0x02
60 #define SA_CONT         0x04
61
62 static int sigproptbl[NSIG] = {
63         SA_KILL,        /* SIGHUP */
64         SA_KILL,        /* SIGINT */
65         SA_KILL,        /* SIGQUIT */
66         SA_KILL,        /* SIGILL */
67         SA_KILL,        /* SIGTRAP */
68         SA_KILL,        /* SIGABRT */
69         SA_KILL,        /* SIGEMT */
70         SA_KILL,        /* SIGFPE */
71         SA_KILL,        /* SIGKILL */
72         SA_KILL,        /* SIGBUS */
73         SA_KILL,        /* SIGSEGV */
74         SA_KILL,        /* SIGSYS */
75         SA_KILL,        /* SIGPIPE */
76         SA_KILL,        /* SIGALRM */
77         SA_KILL,        /* SIGTERM */
78         0,              /* SIGURG */
79         SA_STOP,        /* SIGSTOP */
80         SA_STOP,        /* SIGTSTP */
81         SA_CONT,        /* SIGCONT */
82         0,              /* SIGCHLD */
83         SA_STOP,        /* SIGTTIN */
84         SA_STOP,        /* SIGTTOU */
85         0,              /* SIGIO */
86         SA_KILL,        /* SIGXCPU */
87         SA_KILL,        /* SIGXFSZ */
88         SA_KILL,        /* SIGVTALRM */
89         SA_KILL,        /* SIGPROF */
90         0,              /* SIGWINCH  */
91         0,              /* SIGINFO */
92         SA_KILL,        /* SIGUSR1 */
93         SA_KILL         /* SIGUSR2 */
94 };
95
96 /* #define DEBUG_SIGNAL */
97 #ifdef DEBUG_SIGNAL
98 #define DBG_MSG         stdout_debug
99 #else
100 #define DBG_MSG(x...)
101 #endif
102
103 /*
104  * Signal setup and delivery.
105  *
106  * 1) Delivering signals to threads in the same KSE.
107  *    These signals are sent by upcall events and are set in the
108  *    km_sigscaught field of the KSE mailbox.  Since these signals
109  *    are received while operating on the KSE stack, they can be
110  *    delivered either by using signalcontext() to add a stack frame
111  *    to the target thread's stack, or by adding them in the thread's
112  *    pending set and having the thread run them down after it 
113  * 2) Delivering signals to threads in other KSEs/KSEGs.
114  * 3) Delivering signals to threads in critical regions.
115  * 4) Delivering signals to threads after they change their signal masks.
116  *
117  * Methods of delivering signals.
118  *
119  *   1) Add a signal frame to the thread's saved context.
120  *   2) Add the signal to the thread structure, mark the thread as
121  *      having signals to handle, and let the thread run them down
122  *      after it resumes from the KSE scheduler.
123  *
124  * Problem with 1).  You can't do this to a running thread or a
125  * thread in a critical region.
126  *
127  * Problem with 2).  You can't do this to a thread that doesn't
128  * yield in some way (explicitly enters the scheduler).  A thread
129  * blocked in the kernel or a CPU hungry thread will not see the
130  * signal without entering the scheduler.
131  *
132  * The solution is to use both 1) and 2) to deliver signals:
133  *
134  *   o Thread in critical region - use 2).  When the thread
135  *     leaves the critical region it will check to see if it
136  *     has pending signals and run them down.
137  *
138  *   o Thread enters scheduler explicitly - use 2).  The thread
139  *     can check for pending signals after it returns from the
140  *     the scheduler.
141  *
142  *   o Thread is running and not current thread - use 2).  When the
143  *     thread hits a condition specified by one of the other bullets,
144  *     the signal will be delivered.
145  *
146  *   o Thread is running and is current thread (e.g., the thread
147  *     has just changed its signal mask and now sees that it has
148  *     pending signals) - just run down the pending signals.
149  *
150  *   o Thread is swapped out due to quantum expiration - use 1)
151  *
152  *   o Thread is blocked in kernel - kse_thr_wakeup() and then
153  *     use 1)
154  */
155
156 /*
157  * Rules for selecting threads for signals received:
158  *
159  *   1) If the signal is a sychronous signal, it is delivered to
160  *      the generating (current thread).  If the thread has the
161  *      signal masked, it is added to the threads pending signal
162  *      set until the thread unmasks it.
163  *
164  *   2) A thread in sigwait() where the signal is in the thread's
165  *      waitset.
166  *
167  *   3) A thread in sigsuspend() where the signal is not in the
168  *      thread's suspended signal mask.
169  *
170  *   4) Any thread (first found/easiest to deliver) that has the
171  *      signal unmasked.
172  */
173
174 #ifndef SYSTEM_SCOPE_ONLY
175
176 static void *
177 sig_daemon(void *arg /* Unused */)
178 {
179         int i;
180         kse_critical_t crit;
181         struct timespec ts;
182         sigset_t set;
183         struct kse *curkse;
184         struct pthread *curthread = _get_curthread();
185
186         DBG_MSG("signal daemon started(%p)\n", curthread);
187         
188         curthread->name = strdup("signal thread");
189         crit = _kse_critical_enter();
190         curkse = _get_curkse();
191
192         /*
193          * Daemon thread is a bound thread and we must be created with
194          * all signals masked
195          */
196 #if 0   
197         SIGFILLSET(set);
198         __sys_sigprocmask(SIG_SETMASK, &set, NULL);
199 #endif  
200         __sys_sigpending(&set);
201         ts.tv_sec = 0;
202         ts.tv_nsec = 0;
203         while (1) {
204                 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
205                 _thr_proc_sigpending = set;
206                 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
207                 for (i = 1; i <= _SIG_MAXSIG; i++) {
208                         if (SIGISMEMBER(set, i) != 0)
209                                 _thr_sig_dispatch(curkse, i,
210                                     NULL /* no siginfo */);
211                 }
212                 ts.tv_sec = 30;
213                 ts.tv_nsec = 0;
214                 curkse->k_kcb->kcb_kmbx.km_flags =
215                     KMF_NOUPCALL | KMF_NOCOMPLETED | KMF_WAITSIGEVENT;
216                 kse_release(&ts);
217                 curkse->k_kcb->kcb_kmbx.km_flags = 0;
218                 set = curkse->k_kcb->kcb_kmbx.km_sigscaught;
219         }
220         return (0);
221 }
222
223
224 /* Utility function to create signal daemon thread */
225 int
226 _thr_start_sig_daemon(void)
227 {
228         pthread_attr_t attr;
229         sigset_t sigset, oldset;
230
231         SIGFILLSET(sigset);
232         pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
233         pthread_attr_init(&attr);
234         pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
235         /* sigmask will be inherited */
236         if (pthread_create(&_thr_sig_daemon, &attr, sig_daemon, NULL))
237                 PANIC("can not create signal daemon thread!\n");
238         pthread_attr_destroy(&attr);
239         pthread_sigmask(SIG_SETMASK, &oldset, NULL);
240         return (0);
241 }
242
243 /*
244  * This signal handler only delivers asynchronous signals.
245  * This must be called with upcalls disabled and without
246  * holding any locks.
247  */
248 void
249 _thr_sig_dispatch(struct kse *curkse, int sig, siginfo_t *info)
250 {
251         struct kse_mailbox *kmbx;
252         struct pthread *thread;
253
254         DBG_MSG(">>> _thr_sig_dispatch(%d)\n", sig);
255
256         /* Some signals need special handling: */
257         handle_special_signals(curkse, sig);
258
259         /* Check if the signal requires a dump of thread information: */
260         if (sig == SIGINFO) {
261                 /* Dump thread information to file: */
262                 _thread_dump_info();
263         }
264
265         while ((thread = thr_sig_find(curkse, sig, info)) != NULL) {
266                 /*
267                  * Setup the target thread to receive the signal:
268                  */
269                 DBG_MSG("Got signal %d, selecting thread %p\n", sig, thread);
270                 KSE_SCHED_LOCK(curkse, thread->kseg);
271                 if ((thread->state == PS_DEAD) ||
272                     (thread->state == PS_DEADLOCK) ||
273                     THR_IS_EXITING(thread) || THR_IS_SUSPENDED(thread)) {
274                         KSE_SCHED_UNLOCK(curkse, thread->kseg);
275                         _thr_ref_delete(NULL, thread);
276                 } else if (SIGISMEMBER(thread->sigmask, sig)) {
277                         KSE_SCHED_UNLOCK(curkse, thread->kseg);
278                         _thr_ref_delete(NULL, thread);
279                 } else {
280                         kmbx = _thr_sig_add(thread, sig, info);
281                         KSE_SCHED_UNLOCK(curkse, thread->kseg);
282                         _thr_ref_delete(NULL, thread);
283                         if (kmbx != NULL)
284                                 kse_wakeup(kmbx);
285                         break;
286                 }
287         }
288         DBG_MSG("<<< _thr_sig_dispatch\n");
289 }
290
291 #endif /* ! SYSTEM_SCOPE_ONLY */
292
293 static __inline int
294 sigprop(int sig)
295 {
296
297         if (sig > 0 && sig < NSIG)
298                 return (sigproptbl[_SIG_IDX(sig)]);
299         return (0);
300 }
301
302 typedef void (*ohandler)(int sig, int code,
303         struct sigcontext *scp, char *addr, __sighandler_t *catcher);
304
305 void
306 _thr_sig_handler(int sig, siginfo_t *info, ucontext_t *ucp)
307 {
308         __siginfohandler_t *sigfunc;
309         struct pthread *curthread;
310         struct kse *curkse;
311         struct sigaction act;
312         int sa_flags, err_save, intr_save, timeout_save;
313
314         DBG_MSG(">>> _thr_sig_handler(%d)\n", sig);
315
316         curthread = _get_curthread();
317         if (curthread == NULL)
318                 PANIC("No current thread.\n");
319         if (!(curthread->attr.flags & PTHREAD_SCOPE_SYSTEM))
320                 PANIC("Thread is not system scope.\n");
321         if (curthread->flags & THR_FLAGS_EXITING)
322                 return;
323         curkse = _get_curkse();
324         /*
325          * If thread is in critical region or if thread is on
326          * the way of state transition, then latch signal into buffer.
327          */
328         if (_kse_in_critical() || THR_IN_CRITICAL(curthread) ||
329             (curthread->state != PS_RUNNING && curthread->curframe == NULL)) {
330                 DBG_MSG(">>> _thr_sig_handler(%d) in critical\n", sig);
331                 curthread->siginfo[sig-1] = *info;
332                 curthread->check_pending = 1;
333                 curkse->k_sigseqno++;
334                 SIGADDSET(curthread->sigpend, sig);
335                 /* 
336                  * If the kse is on the way to idle itself, but
337                  * we have signal ready, we should prevent it
338                  * to sleep, kernel will latch the wakeup request,
339                  * so kse_release will return from kernel immediately.
340                  */
341                 if (KSE_IS_IDLE(curkse))
342                         kse_wakeup(&curkse->k_kcb->kcb_kmbx);
343                 return;
344         }
345
346         /* It is now safe to invoke signal handler */
347         err_save = errno;
348         timeout_save = curthread->timeout;
349         intr_save = curthread->interrupted;
350         _kse_critical_enter();
351         /* Get a fresh copy of signal mask */
352         __sys_sigprocmask(SIG_BLOCK, NULL, &curthread->sigmask);
353         KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
354         sigfunc = _thread_sigact[sig - 1].sa_sigaction;
355         sa_flags = _thread_sigact[sig - 1].sa_flags;
356         if (sa_flags & SA_RESETHAND) {
357                 act.sa_handler = SIG_DFL;
358                 act.sa_flags = SA_RESTART;
359                 SIGEMPTYSET(act.sa_mask);
360                 __sys_sigaction(sig, &act, NULL);
361                 __sys_sigaction(sig, NULL, &_thread_sigact[sig - 1]);
362         }
363         KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
364         _kse_critical_leave(&curthread->tcb->tcb_tmbx);
365
366         /* Now invoke real handler */
367         if (((__sighandler_t *)sigfunc != SIG_DFL) &&
368             ((__sighandler_t *)sigfunc != SIG_IGN) && 
369             (sigfunc != (__siginfohandler_t *)_thr_sig_handler)) {
370                 if ((sa_flags & SA_SIGINFO) != 0 || info == NULL)
371                         (*(sigfunc))(sig, info, ucp);
372                 else {
373                         ((ohandler)(*sigfunc))(
374                                 sig, info->si_code, (struct sigcontext *)ucp,
375                                 info->si_addr, (__sighandler_t *)sigfunc);
376                 }
377         } else {
378                 if ((__sighandler_t *)sigfunc == SIG_DFL) {
379                         if (sigprop(sig) & SA_KILL) {
380                                 if (_kse_isthreaded())
381                                         kse_thr_interrupt(NULL,
382                                                  KSE_INTR_SIGEXIT, sig);
383                                 else
384                                         kill(getpid(), sig);
385                         }
386 #ifdef NOTYET
387                         else if (sigprop(sig) & SA_STOP)
388                                 kse_thr_interrupt(NULL, KSE_INTR_JOBSTOP, sig);
389 #endif
390                 }
391         }
392         errno = err_save;
393         curthread->timeout = timeout_save;
394         curthread->interrupted = intr_save;
395         _kse_critical_enter();
396         curthread->sigmask = ucp->uc_sigmask;
397         SIG_CANTMASK(curthread->sigmask);
398         _kse_critical_leave(&curthread->tcb->tcb_tmbx);
399         DBG_MSG("<<< _thr_sig_handler(%d)\n", sig);
400 }
401
402 struct sighandle_info {
403         __siginfohandler_t *sigfunc;
404         int sa_flags;
405         int sig;
406         siginfo_t *info;
407         ucontext_t *ucp;
408 };
409
410 static void handle_signal(struct pthread *curthread,
411         struct sighandle_info *shi);
412 static void handle_signal_altstack(struct pthread *curthread,
413         struct sighandle_info *shi);
414
415 /* Must be called with signal lock and schedule lock held in order */
416 static void
417 thr_sig_invoke_handler(struct pthread *curthread, int sig, siginfo_t *info,
418     ucontext_t *ucp)
419 {
420         __siginfohandler_t *sigfunc;
421         sigset_t sigmask;
422         int sa_flags;
423         int onstack;
424         struct sigaction act;
425         struct kse *curkse;
426         struct sighandle_info shi;
427
428         /*
429          * Invoke the signal handler without going through the scheduler:
430          */
431         DBG_MSG("Got signal %d, calling handler for current thread %p\n",
432             sig, curthread);
433
434         if (!_kse_in_critical())
435                 PANIC("thr_sig_invoke_handler without in critical\n");
436         curkse = _get_curkse();
437         /*
438          * Check that a custom handler is installed and if
439          * the signal is not blocked:
440          */
441         sigfunc = _thread_sigact[sig - 1].sa_sigaction;
442         sa_flags = _thread_sigact[sig - 1].sa_flags;
443         sigmask = curthread->sigmask;
444         SIGSETOR(curthread->sigmask, _thread_sigact[sig - 1].sa_mask);
445         if (!(sa_flags & (SA_NODEFER | SA_RESETHAND)))
446                 SIGADDSET(curthread->sigmask, sig);
447         if ((sig != SIGILL) && (sa_flags & SA_RESETHAND)) {
448                 act.sa_handler = SIG_DFL;
449                 act.sa_flags = SA_RESTART;
450                 SIGEMPTYSET(act.sa_mask);
451                 __sys_sigaction(sig, &act, NULL);
452                 __sys_sigaction(sig, NULL, &_thread_sigact[sig - 1]);
453         }
454         KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
455         KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
456         /*
457          * We are processing buffered signals, synchronize working
458          * signal mask into kernel.
459          */
460         if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
461                 __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL);
462         onstack = _thr_sigonstack(&sigfunc);
463         ucp->uc_stack = curthread->sigstk;
464         ucp->uc_stack.ss_flags = (curthread->sigstk.ss_flags & SS_DISABLE)
465                 ? SS_DISABLE : ((onstack) ? SS_ONSTACK : 0);
466         ucp->uc_sigmask = sigmask;
467         shi.sigfunc = sigfunc;
468         shi.sig = sig;
469         shi.sa_flags = sa_flags;
470         shi.info = info;
471         shi.ucp = ucp;
472         if ((curthread->sigstk.ss_flags & SS_DISABLE) == 0) {
473                 /* Deliver signal on alternative stack */
474                 if (sa_flags & SA_ONSTACK && !onstack)
475                         handle_signal_altstack(curthread, &shi);
476                 else
477                         handle_signal(curthread, &shi);
478         } else {
479                 handle_signal(curthread, &shi);
480         }
481
482         _kse_critical_enter();
483         /* Don't trust after critical leave/enter */
484         curkse = _get_curkse();
485
486         /*
487          * Restore the thread's signal mask.
488          */
489         curthread->sigmask = ucp->uc_sigmask;
490         SIG_CANTMASK(curthread->sigmask);
491         if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
492                 __sys_sigprocmask(SIG_SETMASK, &ucp->uc_sigmask, NULL);
493         KSE_SCHED_LOCK(curkse, curkse->k_kseg);
494         KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
495         
496         DBG_MSG("Got signal %d, handler returned %p\n", sig, curthread);
497 }
498
499 static void
500 handle_signal(struct pthread *curthread, struct sighandle_info *shi)
501 {
502         _kse_critical_leave(&curthread->tcb->tcb_tmbx);
503
504         if (((__sighandler_t *)shi->sigfunc != SIG_DFL) &&
505             ((__sighandler_t *)shi->sigfunc != SIG_IGN)) {
506                 if ((shi->sa_flags & SA_SIGINFO) != 0 || shi->info == NULL)
507                         (*(shi->sigfunc))(shi->sig, shi->info, shi->ucp);
508                 else {
509                         ((ohandler)(*shi->sigfunc))(
510                                 shi->sig, shi->info->si_code,
511                                 (struct sigcontext *)shi->ucp,
512                                 shi->info->si_addr,
513                                 (__sighandler_t *)shi->sigfunc);
514                 }
515         } else {
516                 if ((__sighandler_t *)shi->sigfunc == SIG_DFL) {
517                         if (sigprop(shi->sig) & SA_KILL) {
518                                 if (_kse_isthreaded())
519                                         kse_thr_interrupt(NULL,
520                                                  KSE_INTR_SIGEXIT, shi->sig);
521                                 else
522                                         kill(getpid(), shi->sig);
523                         }
524 #ifdef NOTYET
525                         else if (sigprop(shi->sig) & SA_STOP)
526                                 kse_thr_interrupt(NULL, KSE_INTR_JOBSTOP,
527                                         shi->sig);
528 #endif
529                 }
530         }
531 }
532
533 static void
534 handle_signal_wrapper(struct pthread *curthread, ucontext_t *ret_uc,
535         struct sighandle_info *shi)
536 {
537         shi->ucp->uc_stack.ss_flags = SS_ONSTACK;
538         handle_signal(curthread, shi);
539         if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
540                 setcontext(ret_uc);
541         else {
542                 /* Work around for ia64, THR_SETCONTEXT does not work */
543                 _kse_critical_enter();
544                 curthread->tcb->tcb_tmbx.tm_context = *ret_uc;
545                 _thread_switch(curthread->kse->k_kcb, curthread->tcb, 1);
546                 /* THR_SETCONTEXT */
547         }
548 }
549
550 /*
551  * Jump to stack set by sigaltstack before invoking signal handler
552  */
553 static void
554 handle_signal_altstack(struct pthread *curthread, struct sighandle_info *shi)
555 {
556         volatile int once;
557         ucontext_t uc1, *uc2;
558
559         THR_ASSERT(_kse_in_critical(), "Not in critical");
560
561         once = 0;
562         THR_GETCONTEXT(&uc1);
563         if (once == 0) {
564                 once = 1;
565                 /* XXX
566                  * We are still in critical region, it is safe to operate thread
567                  * context
568                  */
569                 uc2 = &curthread->tcb->tcb_tmbx.tm_context;
570                 uc2->uc_stack = curthread->sigstk;
571                 makecontext(uc2, (void (*)(void))handle_signal_wrapper,
572                         3, curthread, &uc1, shi);
573                 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
574                         setcontext(uc2);
575                 else {
576                         _thread_switch(curthread->kse->k_kcb, curthread->tcb, 1);
577                         /* THR_SETCONTEXT(uc2); */
578                 }
579         }
580 }
581
582 int
583 _thr_getprocsig(int sig, siginfo_t *siginfo)
584 {
585         kse_critical_t crit;
586         struct kse *curkse;
587         int ret;
588
589         DBG_MSG(">>> _thr_getprocsig\n");
590
591         crit = _kse_critical_enter();
592         curkse = _get_curkse();
593         KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
594         ret = _thr_getprocsig_unlocked(sig, siginfo);
595         KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
596         _kse_critical_leave(crit);
597
598         DBG_MSG("<<< _thr_getprocsig\n");
599         return (ret);
600 }
601
602 int
603 _thr_getprocsig_unlocked(int sig, siginfo_t *siginfo)
604 {
605         sigset_t sigset;
606         struct timespec ts;
607
608         /* try to retrieve signal from kernel */
609         SIGEMPTYSET(sigset);
610         SIGADDSET(sigset, sig);
611         ts.tv_sec = 0;
612         ts.tv_nsec = 0;
613         SIGDELSET(_thr_proc_sigpending, sig);
614         if (__sys_sigtimedwait(&sigset, siginfo, &ts) > 0)
615                 return (sig);
616         return (0);
617 }
618
619 #ifndef SYSTEM_SCOPE_ONLY
620 /*
621  * Find a thread that can handle the signal.  This must be called
622  * with upcalls disabled.
623  */
624 struct pthread *
625 thr_sig_find(struct kse *curkse, int sig, siginfo_t *info)
626 {
627         struct kse_mailbox *kmbx = NULL;
628         struct pthread  *pthread;
629         struct pthread  *suspended_thread, *signaled_thread;
630         __siginfohandler_t *sigfunc;
631         siginfo_t si;
632
633         DBG_MSG("Looking for thread to handle signal %d\n", sig);
634
635         /*
636          * Enter a loop to look for threads that have the signal
637          * unmasked.  POSIX specifies that a thread in a sigwait
638          * will get the signal over any other threads.  Second
639          * preference will be threads in in a sigsuspend.  Third
640          * preference will be the current thread.  If none of the
641          * above, then the signal is delivered to the first thread
642          * that is found.  Note that if a custom handler is not
643          * installed, the signal only affects threads in sigwait.
644          */
645         suspended_thread = NULL;
646         signaled_thread = NULL;
647
648         KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock);
649         TAILQ_FOREACH(pthread, &_thread_list, tle) {
650                 if (pthread == _thr_sig_daemon)
651                         continue;
652                 /* Signal delivering to bound thread is done by kernel */
653                 if (pthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
654                         continue;
655                 /* Take the scheduling lock. */
656                 KSE_SCHED_LOCK(curkse, pthread->kseg);
657                 if ((pthread->state == PS_DEAD)         ||
658                     (pthread->state == PS_DEADLOCK)     ||
659                     THR_IS_EXITING(pthread)             ||
660                     THR_IS_SUSPENDED(pthread)) {
661                         ; /* Skip this thread. */
662                 } else if (pthread->state == PS_SIGWAIT &&
663                            SIGISMEMBER(*(pthread->data.sigwait->waitset), sig)) {
664                         /*
665                          * retrieve signal from kernel, if it is job control
666                          * signal, and sigaction is SIG_DFL, then we will
667                          * be stopped in kernel, we hold lock here, but that 
668                          * does not matter, because that's job control, and
669                          * whole process should be stopped.
670                          */
671                         if (_thr_getprocsig(sig, &si)) {
672                                 DBG_MSG("Waking thread %p in sigwait"
673                                         " with signal %d\n", pthread, sig);
674                                 /*  where to put siginfo ? */
675                                 *(pthread->data.sigwait->siginfo) = si;
676                                 kmbx = _thr_setrunnable_unlocked(pthread);
677                         }
678                         KSE_SCHED_UNLOCK(curkse, pthread->kseg);
679                         /*
680                          * POSIX doesn't doesn't specify which thread
681                          * will get the signal if there are multiple
682                          * waiters, so we give it to the first thread
683                          * we find.
684                          *
685                          * Do not attempt to deliver this signal
686                          * to other threads and do not add the signal
687                          * to the process pending set.
688                          */
689                         KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
690                         if (kmbx != NULL)
691                                 kse_wakeup(kmbx);
692                         return (NULL);
693                 } else if (!SIGISMEMBER(pthread->sigmask, sig)) {
694                         sigfunc = _thread_sigact[sig - 1].sa_sigaction;
695                         if ((__sighandler_t *)sigfunc == SIG_DFL) {
696                                 if (sigprop(sig) & SA_KILL) {
697                                         kse_thr_interrupt(NULL,
698                                                  KSE_INTR_SIGEXIT, sig);
699                                         /* Never reach */
700                                 }
701                         }
702                         if (pthread->state == PS_SIGSUSPEND) {
703                                 if (suspended_thread == NULL) {
704                                         suspended_thread = pthread;
705                                         suspended_thread->refcount++;
706                                 }
707                         } else if (signaled_thread == NULL) {
708                                 signaled_thread = pthread;
709                                 signaled_thread->refcount++;
710                         }
711                 }
712                 KSE_SCHED_UNLOCK(curkse, pthread->kseg);
713         }
714         KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
715
716         if (suspended_thread != NULL) {
717                 pthread = suspended_thread;
718                 if (signaled_thread)
719                         _thr_ref_delete(NULL, signaled_thread);
720         } else if (signaled_thread) {
721                 pthread = signaled_thread;
722         } else {
723                 pthread = NULL;
724         }
725         return (pthread);
726 }
727 #endif /* ! SYSTEM_SCOPE_ONLY */
728
729 static void
730 build_siginfo(siginfo_t *info, int signo)
731 {
732         bzero(info, sizeof(*info));
733         info->si_signo = signo;
734         info->si_pid = _thr_pid;
735 }
736
737 /*
738  * This is called by a thread when it has pending signals to deliver.
739  * It should only be called from the context of the thread.
740  */
741 void
742 _thr_sig_rundown(struct pthread *curthread, ucontext_t *ucp,
743     struct pthread_sigframe *psf)
744 {
745         int interrupted = curthread->interrupted;
746         int timeout = curthread->timeout;
747         siginfo_t siginfo;
748         int i;
749         kse_critical_t crit;
750         struct kse *curkse;
751         sigset_t sigmask;
752
753         DBG_MSG(">>> thr_sig_rundown (%p)\n", curthread);
754         /* Check the threads previous state: */
755         if ((psf != NULL) && (psf->psf_valid != 0)) {
756                 /*
757                  * Do a little cleanup handling for those threads in
758                  * queues before calling the signal handler.  Signals
759                  * for these threads are temporarily blocked until
760                  * after cleanup handling.
761                  */
762                 switch (psf->psf_state) {
763                 case PS_COND_WAIT:
764                         _cond_wait_backout(curthread);
765                         psf->psf_state = PS_RUNNING;
766                         break;
767         
768                 case PS_MUTEX_WAIT:
769                         _mutex_lock_backout(curthread);
770                         psf->psf_state = PS_RUNNING;
771                         break;
772         
773                 case PS_RUNNING:
774                         break;
775
776                 default:
777                         psf->psf_state = PS_RUNNING;
778                         break;
779                 }
780                 /* XXX see comment in thr_sched_switch_unlocked */
781                 curthread->critical_count--;
782         }
783
784         /*
785          * Lower the priority before calling the handler in case
786          * it never returns (longjmps back):
787          */
788         crit = _kse_critical_enter();
789         curkse = _get_curkse();
790         KSE_SCHED_LOCK(curkse, curkse->k_kseg);
791         KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
792         curthread->active_priority &= ~THR_SIGNAL_PRIORITY;
793         SIGFILLSET(sigmask);
794         while (1) {
795                 /*
796                  * For bound thread, we mask all signals and get a fresh
797                  * copy of signal mask from kernel
798                  */
799                 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
800                         __sys_sigprocmask(SIG_SETMASK, &sigmask,
801                                  &curthread->sigmask);
802                 }
803                 for (i = 1; i <= _SIG_MAXSIG; i++) {
804                         if (SIGISMEMBER(curthread->sigmask, i))
805                                 continue;
806                         if (SIGISMEMBER(curthread->sigpend, i)) {
807                                 SIGDELSET(curthread->sigpend, i);
808                                 siginfo = curthread->siginfo[i-1];
809                                 break;
810                         }
811                         if (!(curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) 
812                             && SIGISMEMBER(_thr_proc_sigpending, i)) {
813                                 if (_thr_getprocsig_unlocked(i, &siginfo))
814                                         break;
815                         }
816                 }
817                 if (i <= _SIG_MAXSIG)
818                         thr_sig_invoke_handler(curthread, i, &siginfo, ucp);
819                 else {
820                         if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
821                                 __sys_sigprocmask(SIG_SETMASK,
822                                                  &curthread->sigmask, NULL);
823                         }
824                         break;
825                 }
826         }
827
828         if (psf != NULL && psf->psf_valid != 0)
829                 thr_sigframe_restore(curthread, psf);
830         curkse = _get_curkse();
831         KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
832         KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
833         _kse_critical_leave(&curthread->tcb->tcb_tmbx);
834         /* repost masked signal to kernel, it hardly happens in real world */
835         if ((curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
836             !SIGISEMPTY(curthread->sigpend)) { /* dirty read */
837                 __sys_sigprocmask(SIG_SETMASK, &sigmask, &curthread->sigmask);
838                 for (i = 1; i <= _SIG_MAXSIG; ++i) {
839                         if (SIGISMEMBER(curthread->sigpend, i)) {
840                                 SIGDELSET(curthread->sigpend, i);
841                                 if (!_kse_isthreaded())
842                                         kill(getpid(), i);
843                                 else
844                                         kse_thr_interrupt(
845                                                 &curthread->tcb->tcb_tmbx,
846                                                 KSE_INTR_SENDSIG,
847                                                 i);
848                         }
849                 }
850                 __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL);
851         }
852         curthread->interrupted = interrupted;
853         curthread->timeout = timeout;
854
855         DBG_MSG("<<< thr_sig_rundown (%p)\n", curthread);
856 }
857
858 /*
859  * This checks pending signals for the current thread.  It should be
860  * called whenever a thread changes its signal mask.  Note that this
861  * is called from a thread (using its stack).
862  *
863  * XXX - We might want to just check to see if there are pending
864  *       signals for the thread here, but enter the UTS scheduler
865  *       to actually install the signal handler(s).
866  */
867 void
868 _thr_sig_check_pending(struct pthread *curthread)
869 {
870         ucontext_t uc;
871         volatile int once;
872         int errsave;
873
874         if (THR_IN_CRITICAL(curthread))
875                 return;
876
877         errsave = errno;
878         once = 0;
879         THR_GETCONTEXT(&uc);
880         if (once == 0) {
881                 once = 1;
882                 curthread->check_pending = 0;
883                 _thr_sig_rundown(curthread, &uc, NULL);
884         }
885         errno = errsave;
886 }
887
888 #ifndef SYSTEM_SCOPE_ONLY
889 /*
890  * This must be called with upcalls disabled.
891  */
892 static void
893 handle_special_signals(struct kse *curkse, int sig)
894 {
895         switch (sig) {
896         /*
897          * POSIX says that pending SIGCONT signals are
898          * discarded when one of these signals occurs.
899          */
900         case SIGTSTP:
901         case SIGTTIN:
902         case SIGTTOU:
903                 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
904                 SIGDELSET(_thr_proc_sigpending, SIGCONT);
905                 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
906                 break;
907         case SIGCONT:
908                 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
909                 SIGDELSET(_thr_proc_sigpending, SIGTSTP);
910                 SIGDELSET(_thr_proc_sigpending, SIGTTIN);
911                 SIGDELSET(_thr_proc_sigpending, SIGTTOU);
912                 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
913         default:
914                 break;
915         }
916 }
917 #endif /* ! SYSTEM_SCOPE_ONLY */
918
919 /*
920  * Perform thread specific actions in response to a signal.
921  * This function is only called if there is a handler installed
922  * for the signal, and if the target thread has the signal
923  * unmasked.
924  *
925  * This must be called with the thread's scheduling lock held.
926  */
927 struct kse_mailbox *
928 _thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
929 {
930         siginfo_t siginfo;
931         struct kse *curkse;
932         struct kse_mailbox *kmbx = NULL;
933         struct pthread *curthread = _get_curthread();
934         int     restart;
935         int     suppress_handler = 0;
936         int     fromproc = 0;
937         __sighandler_t *sigfunc;
938
939         DBG_MSG(">>> _thr_sig_add %p (%d)\n", pthread, sig);
940
941         curkse = _get_curkse();
942         restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART;
943         sigfunc = _thread_sigact[sig - 1].sa_handler;
944         fromproc = (curthread == _thr_sig_daemon);
945
946         if (pthread->state == PS_DEAD || pthread->state == PS_DEADLOCK ||
947             pthread->state == PS_STATE_MAX)
948                 return (NULL); /* return false */
949
950         if ((pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
951             (curthread != pthread)) {
952                 PANIC("Please use _thr_send_sig for bound thread");
953                 return (NULL);
954         }
955
956         if (pthread->curframe == NULL ||
957             (pthread->state != PS_SIGWAIT &&
958             SIGISMEMBER(pthread->sigmask, sig)) ||
959             THR_IN_CRITICAL(pthread)) {
960                 /* thread is running or signal was being masked */
961                 if (!fromproc) {
962                         SIGADDSET(pthread->sigpend, sig);
963                         if (info == NULL)
964                                 build_siginfo(&pthread->siginfo[sig-1], sig);
965                         else if (info != &pthread->siginfo[sig-1])
966                                 memcpy(&pthread->siginfo[sig-1], info,
967                                          sizeof(*info));
968                 } else {
969                         if (!_thr_getprocsig(sig, &pthread->siginfo[sig-1]))
970                                 return (NULL);
971                         SIGADDSET(pthread->sigpend, sig);
972                 }
973                 if (!SIGISMEMBER(pthread->sigmask, sig)) {
974                         /* A quick path to exit process */
975                         if (sigfunc == SIG_DFL && sigprop(sig) & SA_KILL) {
976                                 kse_thr_interrupt(NULL, KSE_INTR_SIGEXIT, sig);
977                                 /* Never reach */
978                         }
979                         pthread->check_pending = 1;
980                         if (!(pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
981                             (pthread->blocked != 0) && 
982                             !THR_IN_CRITICAL(pthread))
983                                 kse_thr_interrupt(&pthread->tcb->tcb_tmbx,
984                                     restart ? KSE_INTR_RESTART : KSE_INTR_INTERRUPT, 0);
985                 }
986         }
987         else {
988                 /* if process signal not exists, just return */
989                 if (fromproc) {
990                         if (!_thr_getprocsig(sig, &siginfo))
991                                 return (NULL);
992                         info = &siginfo;
993                 }
994
995                 if (pthread->state != PS_SIGWAIT && sigfunc == SIG_DFL &&
996                     (sigprop(sig) & SA_KILL)) {
997                         kse_thr_interrupt(NULL, KSE_INTR_SIGEXIT, sig);
998                         /* Never reach */
999                 }
1000
1001                 /*
1002                  * Process according to thread state:
1003                  */
1004                 switch (pthread->state) {
1005                 case PS_DEAD:
1006                 case PS_DEADLOCK:
1007                 case PS_STATE_MAX:
1008                         return (NULL);  /* XXX return false */
1009                 case PS_LOCKWAIT:
1010                 case PS_SUSPENDED:
1011                         /*
1012                          * You can't call a signal handler for threads in these
1013                          * states.
1014                          */
1015                         suppress_handler = 1;
1016                         break;
1017                 case PS_RUNNING:
1018                         if ((pthread->flags & THR_FLAGS_IN_RUNQ)) {
1019                                 THR_RUNQ_REMOVE(pthread);
1020                                 pthread->active_priority |= THR_SIGNAL_PRIORITY;
1021                                 THR_RUNQ_INSERT_TAIL(pthread);
1022                         } else {
1023                                 /* Possible not in RUNQ and has curframe ? */
1024                                 pthread->active_priority |= THR_SIGNAL_PRIORITY;
1025                         }
1026                         suppress_handler = 1;
1027                         break;
1028                 /*
1029                  * States which cannot be interrupted but still require the
1030                  * signal handler to run:
1031                  */
1032                 case PS_COND_WAIT:
1033                 case PS_MUTEX_WAIT:
1034                         break;
1035
1036                 case PS_SLEEP_WAIT:
1037                         /*
1038                          * Unmasked signals always cause sleep to terminate
1039                          * early regardless of SA_RESTART:
1040                          */
1041                         pthread->interrupted = 1;
1042                         break;
1043
1044                 case PS_JOIN:
1045                         break;
1046
1047                 case PS_SIGSUSPEND:
1048                         pthread->interrupted = 1;
1049                         break;
1050
1051                 case PS_SIGWAIT:
1052                         if (info == NULL)
1053                                 build_siginfo(&pthread->siginfo[sig-1], sig);
1054                         else if (info != &pthread->siginfo[sig-1])
1055                                 memcpy(&pthread->siginfo[sig-1], info,
1056                                         sizeof(*info));
1057                         /*
1058                          * The signal handler is not called for threads in
1059                          * SIGWAIT.
1060                          */
1061                         suppress_handler = 1;
1062                         /* Wake up the thread if the signal is not blocked. */
1063                         if (SIGISMEMBER(*(pthread->data.sigwait->waitset), sig)) {
1064                                 /* Return the signal number: */
1065                                 *(pthread->data.sigwait->siginfo) = pthread->siginfo[sig-1];
1066                                 /* Make the thread runnable: */
1067                                 kmbx = _thr_setrunnable_unlocked(pthread);
1068                         } else {
1069                                 /* Increment the pending signal count. */
1070                                 SIGADDSET(pthread->sigpend, sig);
1071                                 if (!SIGISMEMBER(pthread->sigmask, sig)) {
1072                                         if (sigfunc == SIG_DFL &&
1073                                             sigprop(sig) & SA_KILL) {
1074                                                 kse_thr_interrupt(NULL,
1075                                                          KSE_INTR_SIGEXIT,
1076                                                          sig);
1077                                                 /* Never reach */
1078                                         }
1079                                         pthread->check_pending = 1;
1080                                         pthread->interrupted = 1;
1081                                         kmbx = _thr_setrunnable_unlocked(pthread);
1082                                 }
1083                         }
1084                         return (kmbx);
1085                 }
1086
1087                 SIGADDSET(pthread->sigpend, sig);
1088                 if (info == NULL)
1089                         build_siginfo(&pthread->siginfo[sig-1], sig);
1090                 else if (info != &pthread->siginfo[sig-1])
1091                         memcpy(&pthread->siginfo[sig-1], info, sizeof(*info));
1092
1093                 if (suppress_handler == 0) {
1094                         /*
1095                          * Setup a signal frame and save the current threads
1096                          * state:
1097                          */
1098                         thr_sigframe_add(pthread);
1099                         if (pthread->flags & THR_FLAGS_IN_RUNQ)
1100                                 THR_RUNQ_REMOVE(pthread);
1101                         pthread->active_priority |= THR_SIGNAL_PRIORITY;
1102                         kmbx = _thr_setrunnable_unlocked(pthread);
1103                 } else {
1104                         pthread->check_pending = 1;
1105                 }
1106         }
1107         return (kmbx);
1108 }
1109
1110 /*
1111  * Send a signal to a specific thread (ala pthread_kill):
1112  */
1113 void
1114 _thr_sig_send(struct pthread *pthread, int sig)
1115 {
1116         struct pthread *curthread = _get_curthread();
1117         struct kse_mailbox *kmbx;
1118
1119         if (pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
1120                 kse_thr_interrupt(&pthread->tcb->tcb_tmbx, KSE_INTR_SENDSIG, sig);
1121                 return;
1122         }
1123
1124         /* Lock the scheduling queue of the target thread. */
1125         THR_SCHED_LOCK(curthread, pthread);
1126         if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
1127                 kmbx = _thr_sig_add(pthread, sig, NULL);
1128                 THR_SCHED_UNLOCK(curthread, pthread);
1129                 if (kmbx != NULL)
1130                         kse_wakeup(kmbx);
1131                 /* XXX
1132                  * If thread sent signal to itself, check signals now.
1133                  * It is not really needed, _kse_critical_leave should
1134                  * have already checked signals.
1135                  */
1136                 if (pthread == curthread && curthread->check_pending)
1137                         _thr_sig_check_pending(curthread);
1138         } else  {
1139                 THR_SCHED_UNLOCK(curthread, pthread);
1140         }
1141 }
1142
1143 static void
1144 thr_sigframe_add(struct pthread *thread)
1145 {
1146         if (thread->curframe == NULL)
1147                 PANIC("Thread doesn't have signal frame ");
1148
1149         if (thread->curframe->psf_valid == 0) {
1150                 thread->curframe->psf_valid = 1;
1151                 /*
1152                  * Multiple signals can be added to the same signal
1153                  * frame.  Only save the thread's state the first time.
1154                  */
1155                 thr_sigframe_save(thread, thread->curframe);
1156         }
1157 }
1158
1159 static void
1160 thr_sigframe_restore(struct pthread *thread, struct pthread_sigframe *psf)
1161 {
1162         if (psf->psf_valid == 0)
1163                 PANIC("invalid pthread_sigframe\n");
1164         thread->flags = psf->psf_flags;
1165         thread->interrupted = psf->psf_interrupted;
1166         thread->timeout = psf->psf_timeout;
1167         thread->state = psf->psf_state;
1168         thread->data = psf->psf_wait_data;
1169         thread->wakeup_time = psf->psf_wakeup_time;
1170 }
1171
1172 static void
1173 thr_sigframe_save(struct pthread *thread, struct pthread_sigframe *psf)
1174 {
1175         /* This has to initialize all members of the sigframe. */
1176         psf->psf_flags =
1177             thread->flags & (THR_FLAGS_PRIVATE | THR_FLAGS_IN_TDLIST);
1178         psf->psf_interrupted = thread->interrupted;
1179         psf->psf_timeout = thread->timeout;
1180         psf->psf_state = thread->state;
1181         psf->psf_wait_data = thread->data;
1182         psf->psf_wakeup_time = thread->wakeup_time;
1183 }
1184
1185 void
1186 _thr_signal_init(void)
1187 {
1188         struct sigaction act;
1189         __siginfohandler_t *sigfunc;
1190         int i;
1191         sigset_t sigset;
1192
1193         SIGFILLSET(sigset);
1194         __sys_sigprocmask(SIG_SETMASK, &sigset, &_thr_initial->sigmask);
1195         /* Enter a loop to get the existing signal status: */
1196         for (i = 1; i <= _SIG_MAXSIG; i++) {
1197                 /* Check for signals which cannot be trapped: */
1198                 if (i == SIGKILL || i == SIGSTOP) {
1199                 }
1200
1201                 /* Get the signal handler details: */
1202                 else if (__sys_sigaction(i, NULL,
1203                             &_thread_sigact[i - 1]) != 0) {
1204                         /*
1205                          * Abort this process if signal
1206                          * initialisation fails:
1207                          */
1208                         PANIC("Cannot read signal handler info");
1209                 }
1210                 /* Intall wrapper if handler was set */
1211                 sigfunc = _thread_sigact[i - 1].sa_sigaction;
1212                 if (((__sighandler_t *)sigfunc) != SIG_DFL &&
1213                     ((__sighandler_t *)sigfunc) != SIG_IGN) {
1214                         act = _thread_sigact[i - 1];
1215                         act.sa_flags |= SA_SIGINFO;
1216                         act.sa_sigaction =
1217                                 (__siginfohandler_t *)_thr_sig_handler;
1218                         __sys_sigaction(i, &act, NULL);
1219                 }
1220         }
1221         /*
1222          * Install the signal handler for SIGINFO.  It isn't
1223          * really needed, but it is nice to have for debugging
1224          * purposes.
1225          */
1226         _thread_sigact[SIGINFO - 1].sa_flags = SA_SIGINFO | SA_RESTART;
1227         SIGEMPTYSET(act.sa_mask);
1228         act.sa_flags = SA_SIGINFO | SA_RESTART;
1229         act.sa_sigaction = (__siginfohandler_t *)&_thr_sig_handler;
1230         if (__sys_sigaction(SIGINFO, &act, NULL) != 0) {
1231                 __sys_sigprocmask(SIG_SETMASK, &_thr_initial->sigmask, NULL);
1232                 /*
1233                  * Abort this process if signal initialisation fails:
1234                  */
1235                 PANIC("Cannot initialize signal handler");
1236         }
1237         __sys_sigprocmask(SIG_SETMASK, &_thr_initial->sigmask, NULL);
1238         __sys_sigaltstack(NULL, &_thr_initial->sigstk);
1239 }
1240
1241 void
1242 _thr_signal_deinit(void)
1243 {
1244         int i;
1245         struct pthread *curthread = _get_curthread();
1246
1247         /* Enter a loop to get the existing signal status: */
1248         for (i = 1; i <= _SIG_MAXSIG; i++) {
1249                 /* Check for signals which cannot be trapped: */
1250                 if (i == SIGKILL || i == SIGSTOP) {
1251                 }
1252
1253                 /* Set the signal handler details: */
1254                 else if (__sys_sigaction(i, &_thread_sigact[i - 1],
1255                          NULL) != 0) {
1256                         /*
1257                          * Abort this process if signal
1258                          * initialisation fails:
1259                          */
1260                         PANIC("Cannot set signal handler info");
1261                 }
1262         }
1263         __sys_sigaltstack(&curthread->sigstk, NULL);
1264 }
1265