]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libkse/thread/thr_sig.c
This commit was generated by cvs2svn to compensate for changes in r131702,
[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         if (curthread->oldsigmask) {
467                 ucp->uc_sigmask = *(curthread->oldsigmask);
468                 curthread->oldsigmask = NULL;
469         } else
470                 ucp->uc_sigmask = sigmask;
471         shi.sigfunc = sigfunc;
472         shi.sig = sig;
473         shi.sa_flags = sa_flags;
474         shi.info = info;
475         shi.ucp = ucp;
476         if ((curthread->sigstk.ss_flags & SS_DISABLE) == 0) {
477                 /* Deliver signal on alternative stack */
478                 if (sa_flags & SA_ONSTACK && !onstack)
479                         handle_signal_altstack(curthread, &shi);
480                 else
481                         handle_signal(curthread, &shi);
482         } else {
483                 handle_signal(curthread, &shi);
484         }
485
486         _kse_critical_enter();
487         /* Don't trust after critical leave/enter */
488         curkse = _get_curkse();
489
490         /*
491          * Restore the thread's signal mask.
492          */
493         curthread->sigmask = ucp->uc_sigmask;
494         SIG_CANTMASK(curthread->sigmask);
495         if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
496                 __sys_sigprocmask(SIG_SETMASK, &ucp->uc_sigmask, NULL);
497         KSE_SCHED_LOCK(curkse, curkse->k_kseg);
498         KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
499         
500         DBG_MSG("Got signal %d, handler returned %p\n", sig, curthread);
501 }
502
503 static void
504 handle_signal(struct pthread *curthread, struct sighandle_info *shi)
505 {
506         _kse_critical_leave(&curthread->tcb->tcb_tmbx);
507
508         if (((__sighandler_t *)shi->sigfunc != SIG_DFL) &&
509             ((__sighandler_t *)shi->sigfunc != SIG_IGN)) {
510                 if ((shi->sa_flags & SA_SIGINFO) != 0 || shi->info == NULL)
511                         (*(shi->sigfunc))(shi->sig, shi->info, shi->ucp);
512                 else {
513                         ((ohandler)(*shi->sigfunc))(
514                                 shi->sig, shi->info->si_code,
515                                 (struct sigcontext *)shi->ucp,
516                                 shi->info->si_addr,
517                                 (__sighandler_t *)shi->sigfunc);
518                 }
519         } else {
520                 if ((__sighandler_t *)shi->sigfunc == SIG_DFL) {
521                         if (sigprop(shi->sig) & SA_KILL) {
522                                 if (_kse_isthreaded())
523                                         kse_thr_interrupt(NULL,
524                                                  KSE_INTR_SIGEXIT, shi->sig);
525                                 else
526                                         kill(getpid(), shi->sig);
527                         }
528 #ifdef NOTYET
529                         else if (sigprop(shi->sig) & SA_STOP)
530                                 kse_thr_interrupt(NULL, KSE_INTR_JOBSTOP,
531                                         shi->sig);
532 #endif
533                 }
534         }
535 }
536
537 static void
538 handle_signal_wrapper(struct pthread *curthread, ucontext_t *ret_uc,
539         struct sighandle_info *shi)
540 {
541         shi->ucp->uc_stack.ss_flags = SS_ONSTACK;
542         handle_signal(curthread, shi);
543         if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
544                 setcontext(ret_uc);
545         else {
546                 /* Work around for ia64, THR_SETCONTEXT does not work */
547                 _kse_critical_enter();
548                 curthread->tcb->tcb_tmbx.tm_context = *ret_uc;
549                 _thread_switch(curthread->kse->k_kcb, curthread->tcb, 1);
550                 /* THR_SETCONTEXT */
551         }
552 }
553
554 /*
555  * Jump to stack set by sigaltstack before invoking signal handler
556  */
557 static void
558 handle_signal_altstack(struct pthread *curthread, struct sighandle_info *shi)
559 {
560         volatile int once;
561         ucontext_t uc1, *uc2;
562
563         THR_ASSERT(_kse_in_critical(), "Not in critical");
564
565         once = 0;
566         THR_GETCONTEXT(&uc1);
567         if (once == 0) {
568                 once = 1;
569                 /* XXX
570                  * We are still in critical region, it is safe to operate thread
571                  * context
572                  */
573                 uc2 = &curthread->tcb->tcb_tmbx.tm_context;
574                 uc2->uc_stack = curthread->sigstk;
575                 makecontext(uc2, (void (*)(void))handle_signal_wrapper,
576                         3, curthread, &uc1, shi);
577                 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
578                         setcontext(uc2);
579                 else {
580                         _thread_switch(curthread->kse->k_kcb, curthread->tcb, 1);
581                         /* THR_SETCONTEXT(uc2); */
582                 }
583         }
584 }
585
586 int
587 _thr_getprocsig(int sig, siginfo_t *siginfo)
588 {
589         kse_critical_t crit;
590         struct kse *curkse;
591         int ret;
592
593         DBG_MSG(">>> _thr_getprocsig\n");
594
595         crit = _kse_critical_enter();
596         curkse = _get_curkse();
597         KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
598         ret = _thr_getprocsig_unlocked(sig, siginfo);
599         KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
600         _kse_critical_leave(crit);
601
602         DBG_MSG("<<< _thr_getprocsig\n");
603         return (ret);
604 }
605
606 int
607 _thr_getprocsig_unlocked(int sig, siginfo_t *siginfo)
608 {
609         sigset_t sigset;
610         struct timespec ts;
611
612         /* try to retrieve signal from kernel */
613         SIGEMPTYSET(sigset);
614         SIGADDSET(sigset, sig);
615         ts.tv_sec = 0;
616         ts.tv_nsec = 0;
617         SIGDELSET(_thr_proc_sigpending, sig);
618         if (__sys_sigtimedwait(&sigset, siginfo, &ts) > 0)
619                 return (sig);
620         return (0);
621 }
622
623 #ifndef SYSTEM_SCOPE_ONLY
624 /*
625  * Find a thread that can handle the signal.  This must be called
626  * with upcalls disabled.
627  */
628 struct pthread *
629 thr_sig_find(struct kse *curkse, int sig, siginfo_t *info)
630 {
631         struct kse_mailbox *kmbx = NULL;
632         struct pthread  *pthread;
633         struct pthread  *suspended_thread, *signaled_thread;
634         __siginfohandler_t *sigfunc;
635         siginfo_t si;
636
637         DBG_MSG("Looking for thread to handle signal %d\n", sig);
638
639         /*
640          * Enter a loop to look for threads that have the signal
641          * unmasked.  POSIX specifies that a thread in a sigwait
642          * will get the signal over any other threads.  Second
643          * preference will be threads in in a sigsuspend.  Third
644          * preference will be the current thread.  If none of the
645          * above, then the signal is delivered to the first thread
646          * that is found.  Note that if a custom handler is not
647          * installed, the signal only affects threads in sigwait.
648          */
649         suspended_thread = NULL;
650         signaled_thread = NULL;
651
652         KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock);
653         TAILQ_FOREACH(pthread, &_thread_list, tle) {
654                 if (pthread == _thr_sig_daemon)
655                         continue;
656                 /* Signal delivering to bound thread is done by kernel */
657                 if (pthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
658                         continue;
659                 /* Take the scheduling lock. */
660                 KSE_SCHED_LOCK(curkse, pthread->kseg);
661                 if ((pthread->state == PS_DEAD)         ||
662                     (pthread->state == PS_DEADLOCK)     ||
663                     THR_IS_EXITING(pthread)             ||
664                     THR_IS_SUSPENDED(pthread)) {
665                         ; /* Skip this thread. */
666                 } else if (pthread->state == PS_SIGWAIT &&
667                            SIGISMEMBER(*(pthread->data.sigwait->waitset), sig)) {
668                         /*
669                          * retrieve signal from kernel, if it is job control
670                          * signal, and sigaction is SIG_DFL, then we will
671                          * be stopped in kernel, we hold lock here, but that 
672                          * does not matter, because that's job control, and
673                          * whole process should be stopped.
674                          */
675                         if (_thr_getprocsig(sig, &si)) {
676                                 DBG_MSG("Waking thread %p in sigwait"
677                                         " with signal %d\n", pthread, sig);
678                                 /*  where to put siginfo ? */
679                                 *(pthread->data.sigwait->siginfo) = si;
680                                 kmbx = _thr_setrunnable_unlocked(pthread);
681                         }
682                         KSE_SCHED_UNLOCK(curkse, pthread->kseg);
683                         /*
684                          * POSIX doesn't doesn't specify which thread
685                          * will get the signal if there are multiple
686                          * waiters, so we give it to the first thread
687                          * we find.
688                          *
689                          * Do not attempt to deliver this signal
690                          * to other threads and do not add the signal
691                          * to the process pending set.
692                          */
693                         KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
694                         if (kmbx != NULL)
695                                 kse_wakeup(kmbx);
696                         return (NULL);
697                 } else if (!SIGISMEMBER(pthread->sigmask, sig)) {
698                         sigfunc = _thread_sigact[sig - 1].sa_sigaction;
699                         if ((__sighandler_t *)sigfunc == SIG_DFL) {
700                                 if (sigprop(sig) & SA_KILL) {
701                                         kse_thr_interrupt(NULL,
702                                                  KSE_INTR_SIGEXIT, sig);
703                                         /* Never reach */
704                                 }
705                         }
706                         if (pthread->state == PS_SIGSUSPEND) {
707                                 if (suspended_thread == NULL) {
708                                         suspended_thread = pthread;
709                                         suspended_thread->refcount++;
710                                 }
711                         } else if (signaled_thread == NULL) {
712                                 signaled_thread = pthread;
713                                 signaled_thread->refcount++;
714                         }
715                 }
716                 KSE_SCHED_UNLOCK(curkse, pthread->kseg);
717         }
718         KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
719
720         if (suspended_thread != NULL) {
721                 pthread = suspended_thread;
722                 if (signaled_thread)
723                         _thr_ref_delete(NULL, signaled_thread);
724         } else if (signaled_thread) {
725                 pthread = signaled_thread;
726         } else {
727                 pthread = NULL;
728         }
729         return (pthread);
730 }
731 #endif /* ! SYSTEM_SCOPE_ONLY */
732
733 static void
734 build_siginfo(siginfo_t *info, int signo)
735 {
736         bzero(info, sizeof(*info));
737         info->si_signo = signo;
738         info->si_pid = _thr_pid;
739 }
740
741 /*
742  * This is called by a thread when it has pending signals to deliver.
743  * It should only be called from the context of the thread.
744  */
745 void
746 _thr_sig_rundown(struct pthread *curthread, ucontext_t *ucp,
747     struct pthread_sigframe *psf)
748 {
749         int interrupted = curthread->interrupted;
750         int timeout = curthread->timeout;
751         siginfo_t siginfo;
752         int i;
753         kse_critical_t crit;
754         struct kse *curkse;
755         sigset_t sigmask;
756
757         DBG_MSG(">>> thr_sig_rundown (%p)\n", curthread);
758         /* Check the threads previous state: */
759         if ((psf != NULL) && (psf->psf_valid != 0)) {
760                 /*
761                  * Do a little cleanup handling for those threads in
762                  * queues before calling the signal handler.  Signals
763                  * for these threads are temporarily blocked until
764                  * after cleanup handling.
765                  */
766                 switch (psf->psf_state) {
767                 case PS_COND_WAIT:
768                         _cond_wait_backout(curthread);
769                         psf->psf_state = PS_RUNNING;
770                         break;
771         
772                 case PS_MUTEX_WAIT:
773                         _mutex_lock_backout(curthread);
774                         psf->psf_state = PS_RUNNING;
775                         break;
776         
777                 case PS_RUNNING:
778                         break;
779
780                 default:
781                         psf->psf_state = PS_RUNNING;
782                         break;
783                 }
784                 /* XXX see comment in thr_sched_switch_unlocked */
785                 curthread->critical_count--;
786         }
787
788         /*
789          * Lower the priority before calling the handler in case
790          * it never returns (longjmps back):
791          */
792         crit = _kse_critical_enter();
793         curkse = _get_curkse();
794         KSE_SCHED_LOCK(curkse, curkse->k_kseg);
795         KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
796         curthread->active_priority &= ~THR_SIGNAL_PRIORITY;
797         SIGFILLSET(sigmask);
798         while (1) {
799                 /*
800                  * For bound thread, we mask all signals and get a fresh
801                  * copy of signal mask from kernel
802                  */
803                 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
804                         __sys_sigprocmask(SIG_SETMASK, &sigmask,
805                                  &curthread->sigmask);
806                 }
807                 for (i = 1; i <= _SIG_MAXSIG; i++) {
808                         if (SIGISMEMBER(curthread->sigmask, i))
809                                 continue;
810                         if (SIGISMEMBER(curthread->sigpend, i)) {
811                                 SIGDELSET(curthread->sigpend, i);
812                                 siginfo = curthread->siginfo[i-1];
813                                 break;
814                         }
815                         if (!(curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) 
816                             && SIGISMEMBER(_thr_proc_sigpending, i)) {
817                                 if (_thr_getprocsig_unlocked(i, &siginfo))
818                                         break;
819                         }
820                 }
821                 if (i <= _SIG_MAXSIG)
822                         thr_sig_invoke_handler(curthread, i, &siginfo, ucp);
823                 else {
824                         if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
825                                 __sys_sigprocmask(SIG_SETMASK,
826                                                  &curthread->sigmask, NULL);
827                         }
828                         break;
829                 }
830         }
831
832         if (psf != NULL && psf->psf_valid != 0)
833                 thr_sigframe_restore(curthread, psf);
834         curkse = _get_curkse();
835         KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
836         KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
837         _kse_critical_leave(&curthread->tcb->tcb_tmbx);
838         /* repost masked signal to kernel, it hardly happens in real world */
839         if ((curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
840             !SIGISEMPTY(curthread->sigpend)) { /* dirty read */
841                 __sys_sigprocmask(SIG_SETMASK, &sigmask, &curthread->sigmask);
842                 for (i = 1; i <= _SIG_MAXSIG; ++i) {
843                         if (SIGISMEMBER(curthread->sigpend, i)) {
844                                 SIGDELSET(curthread->sigpend, i);
845                                 if (!_kse_isthreaded())
846                                         kill(getpid(), i);
847                                 else
848                                         kse_thr_interrupt(
849                                                 &curthread->tcb->tcb_tmbx,
850                                                 KSE_INTR_SENDSIG,
851                                                 i);
852                         }
853                 }
854                 __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL);
855         }
856         curthread->interrupted = interrupted;
857         curthread->timeout = timeout;
858
859         DBG_MSG("<<< thr_sig_rundown (%p)\n", curthread);
860 }
861
862 /*
863  * This checks pending signals for the current thread.  It should be
864  * called whenever a thread changes its signal mask.  Note that this
865  * is called from a thread (using its stack).
866  *
867  * XXX - We might want to just check to see if there are pending
868  *       signals for the thread here, but enter the UTS scheduler
869  *       to actually install the signal handler(s).
870  */
871 void
872 _thr_sig_check_pending(struct pthread *curthread)
873 {
874         ucontext_t uc;
875         volatile int once;
876         int errsave;
877
878         if (THR_IN_CRITICAL(curthread))
879                 return;
880
881         errsave = errno;
882         once = 0;
883         THR_GETCONTEXT(&uc);
884         if (once == 0) {
885                 once = 1;
886                 curthread->check_pending = 0;
887                 _thr_sig_rundown(curthread, &uc, NULL);
888         }
889         errno = errsave;
890 }
891
892 #ifndef SYSTEM_SCOPE_ONLY
893 /*
894  * This must be called with upcalls disabled.
895  */
896 static void
897 handle_special_signals(struct kse *curkse, int sig)
898 {
899         switch (sig) {
900         /*
901          * POSIX says that pending SIGCONT signals are
902          * discarded when one of these signals occurs.
903          */
904         case SIGTSTP:
905         case SIGTTIN:
906         case SIGTTOU:
907                 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
908                 SIGDELSET(_thr_proc_sigpending, SIGCONT);
909                 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
910                 break;
911         case SIGCONT:
912                 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
913                 SIGDELSET(_thr_proc_sigpending, SIGTSTP);
914                 SIGDELSET(_thr_proc_sigpending, SIGTTIN);
915                 SIGDELSET(_thr_proc_sigpending, SIGTTOU);
916                 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
917         default:
918                 break;
919         }
920 }
921 #endif /* ! SYSTEM_SCOPE_ONLY */
922
923 /*
924  * Perform thread specific actions in response to a signal.
925  * This function is only called if there is a handler installed
926  * for the signal, and if the target thread has the signal
927  * unmasked.
928  *
929  * This must be called with the thread's scheduling lock held.
930  */
931 struct kse_mailbox *
932 _thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
933 {
934         siginfo_t siginfo;
935         struct kse *curkse;
936         struct kse_mailbox *kmbx = NULL;
937         struct pthread *curthread = _get_curthread();
938         int     restart;
939         int     suppress_handler = 0;
940         int     fromproc = 0;
941         __sighandler_t *sigfunc;
942
943         DBG_MSG(">>> _thr_sig_add %p (%d)\n", pthread, sig);
944
945         curkse = _get_curkse();
946         restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART;
947         sigfunc = _thread_sigact[sig - 1].sa_handler;
948         fromproc = (curthread == _thr_sig_daemon);
949
950         if (pthread->state == PS_DEAD || pthread->state == PS_DEADLOCK ||
951             pthread->state == PS_STATE_MAX)
952                 return (NULL); /* return false */
953
954         if ((pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
955             (curthread != pthread)) {
956                 PANIC("Please use _thr_send_sig for bound thread");
957                 return (NULL);
958         }
959
960         if (pthread->curframe == NULL ||
961             (pthread->state != PS_SIGWAIT &&
962             SIGISMEMBER(pthread->sigmask, sig)) ||
963             THR_IN_CRITICAL(pthread)) {
964                 /* thread is running or signal was being masked */
965                 if (!fromproc) {
966                         SIGADDSET(pthread->sigpend, sig);
967                         if (info == NULL)
968                                 build_siginfo(&pthread->siginfo[sig-1], sig);
969                         else if (info != &pthread->siginfo[sig-1])
970                                 memcpy(&pthread->siginfo[sig-1], info,
971                                          sizeof(*info));
972                 } else {
973                         if (!_thr_getprocsig(sig, &pthread->siginfo[sig-1]))
974                                 return (NULL);
975                         SIGADDSET(pthread->sigpend, sig);
976                 }
977                 if (!SIGISMEMBER(pthread->sigmask, sig)) {
978                         /* A quick path to exit process */
979                         if (sigfunc == SIG_DFL && sigprop(sig) & SA_KILL) {
980                                 kse_thr_interrupt(NULL, KSE_INTR_SIGEXIT, sig);
981                                 /* Never reach */
982                         }
983                         pthread->check_pending = 1;
984                         if (!(pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) &&
985                             (pthread->blocked != 0) && 
986                             !THR_IN_CRITICAL(pthread))
987                                 kse_thr_interrupt(&pthread->tcb->tcb_tmbx,
988                                     restart ? KSE_INTR_RESTART : KSE_INTR_INTERRUPT, 0);
989                 }
990         }
991         else {
992                 /* if process signal not exists, just return */
993                 if (fromproc) {
994                         if (!_thr_getprocsig(sig, &siginfo))
995                                 return (NULL);
996                         info = &siginfo;
997                 }
998
999                 if (pthread->state != PS_SIGWAIT && sigfunc == SIG_DFL &&
1000                     (sigprop(sig) & SA_KILL)) {
1001                         kse_thr_interrupt(NULL, KSE_INTR_SIGEXIT, sig);
1002                         /* Never reach */
1003                 }
1004
1005                 /*
1006                  * Process according to thread state:
1007                  */
1008                 switch (pthread->state) {
1009                 case PS_DEAD:
1010                 case PS_DEADLOCK:
1011                 case PS_STATE_MAX:
1012                         return (NULL);  /* XXX return false */
1013                 case PS_LOCKWAIT:
1014                 case PS_SUSPENDED:
1015                         /*
1016                          * You can't call a signal handler for threads in these
1017                          * states.
1018                          */
1019                         suppress_handler = 1;
1020                         break;
1021                 case PS_RUNNING:
1022                         if ((pthread->flags & THR_FLAGS_IN_RUNQ)) {
1023                                 THR_RUNQ_REMOVE(pthread);
1024                                 pthread->active_priority |= THR_SIGNAL_PRIORITY;
1025                                 THR_RUNQ_INSERT_TAIL(pthread);
1026                         } else {
1027                                 /* Possible not in RUNQ and has curframe ? */
1028                                 pthread->active_priority |= THR_SIGNAL_PRIORITY;
1029                         }
1030                         suppress_handler = 1;
1031                         break;
1032                 /*
1033                  * States which cannot be interrupted but still require the
1034                  * signal handler to run:
1035                  */
1036                 case PS_COND_WAIT:
1037                 case PS_MUTEX_WAIT:
1038                         break;
1039
1040                 case PS_SLEEP_WAIT:
1041                         /*
1042                          * Unmasked signals always cause sleep to terminate
1043                          * early regardless of SA_RESTART:
1044                          */
1045                         pthread->interrupted = 1;
1046                         break;
1047
1048                 case PS_JOIN:
1049                         break;
1050
1051                 case PS_SIGSUSPEND:
1052                         pthread->interrupted = 1;
1053                         break;
1054
1055                 case PS_SIGWAIT:
1056                         if (info == NULL)
1057                                 build_siginfo(&pthread->siginfo[sig-1], sig);
1058                         else if (info != &pthread->siginfo[sig-1])
1059                                 memcpy(&pthread->siginfo[sig-1], info,
1060                                         sizeof(*info));
1061                         /*
1062                          * The signal handler is not called for threads in
1063                          * SIGWAIT.
1064                          */
1065                         suppress_handler = 1;
1066                         /* Wake up the thread if the signal is not blocked. */
1067                         if (SIGISMEMBER(*(pthread->data.sigwait->waitset), sig)) {
1068                                 /* Return the signal number: */
1069                                 *(pthread->data.sigwait->siginfo) = pthread->siginfo[sig-1];
1070                                 /* Make the thread runnable: */
1071                                 kmbx = _thr_setrunnable_unlocked(pthread);
1072                         } else {
1073                                 /* Increment the pending signal count. */
1074                                 SIGADDSET(pthread->sigpend, sig);
1075                                 if (!SIGISMEMBER(pthread->sigmask, sig)) {
1076                                         if (sigfunc == SIG_DFL &&
1077                                             sigprop(sig) & SA_KILL) {
1078                                                 kse_thr_interrupt(NULL,
1079                                                          KSE_INTR_SIGEXIT,
1080                                                          sig);
1081                                                 /* Never reach */
1082                                         }
1083                                         pthread->check_pending = 1;
1084                                         pthread->interrupted = 1;
1085                                         kmbx = _thr_setrunnable_unlocked(pthread);
1086                                 }
1087                         }
1088                         return (kmbx);
1089                 }
1090
1091                 SIGADDSET(pthread->sigpend, sig);
1092                 if (info == NULL)
1093                         build_siginfo(&pthread->siginfo[sig-1], sig);
1094                 else if (info != &pthread->siginfo[sig-1])
1095                         memcpy(&pthread->siginfo[sig-1], info, sizeof(*info));
1096
1097                 if (suppress_handler == 0) {
1098                         /*
1099                          * Setup a signal frame and save the current threads
1100                          * state:
1101                          */
1102                         thr_sigframe_add(pthread);
1103                         if (pthread->flags & THR_FLAGS_IN_RUNQ)
1104                                 THR_RUNQ_REMOVE(pthread);
1105                         pthread->active_priority |= THR_SIGNAL_PRIORITY;
1106                         kmbx = _thr_setrunnable_unlocked(pthread);
1107                 } else {
1108                         pthread->check_pending = 1;
1109                 }
1110         }
1111         return (kmbx);
1112 }
1113
1114 /*
1115  * Send a signal to a specific thread (ala pthread_kill):
1116  */
1117 void
1118 _thr_sig_send(struct pthread *pthread, int sig)
1119 {
1120         struct pthread *curthread = _get_curthread();
1121         struct kse_mailbox *kmbx;
1122
1123         if (pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
1124                 kse_thr_interrupt(&pthread->tcb->tcb_tmbx, KSE_INTR_SENDSIG, sig);
1125                 return;
1126         }
1127
1128         /* Lock the scheduling queue of the target thread. */
1129         THR_SCHED_LOCK(curthread, pthread);
1130         if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
1131                 kmbx = _thr_sig_add(pthread, sig, NULL);
1132                 THR_SCHED_UNLOCK(curthread, pthread);
1133                 if (kmbx != NULL)
1134                         kse_wakeup(kmbx);
1135                 /* XXX
1136                  * If thread sent signal to itself, check signals now.
1137                  * It is not really needed, _kse_critical_leave should
1138                  * have already checked signals.
1139                  */
1140                 if (pthread == curthread && curthread->check_pending)
1141                         _thr_sig_check_pending(curthread);
1142         } else  {
1143                 THR_SCHED_UNLOCK(curthread, pthread);
1144         }
1145 }
1146
1147 static void
1148 thr_sigframe_add(struct pthread *thread)
1149 {
1150         if (thread->curframe == NULL)
1151                 PANIC("Thread doesn't have signal frame ");
1152
1153         if (thread->curframe->psf_valid == 0) {
1154                 thread->curframe->psf_valid = 1;
1155                 /*
1156                  * Multiple signals can be added to the same signal
1157                  * frame.  Only save the thread's state the first time.
1158                  */
1159                 thr_sigframe_save(thread, thread->curframe);
1160         }
1161 }
1162
1163 static void
1164 thr_sigframe_restore(struct pthread *thread, struct pthread_sigframe *psf)
1165 {
1166         if (psf->psf_valid == 0)
1167                 PANIC("invalid pthread_sigframe\n");
1168         thread->flags = psf->psf_flags;
1169         thread->interrupted = psf->psf_interrupted;
1170         thread->timeout = psf->psf_timeout;
1171         thread->state = psf->psf_state;
1172         thread->data = psf->psf_wait_data;
1173         thread->wakeup_time = psf->psf_wakeup_time;
1174 }
1175
1176 static void
1177 thr_sigframe_save(struct pthread *thread, struct pthread_sigframe *psf)
1178 {
1179         /* This has to initialize all members of the sigframe. */
1180         psf->psf_flags =
1181             thread->flags & (THR_FLAGS_PRIVATE | THR_FLAGS_IN_TDLIST);
1182         psf->psf_interrupted = thread->interrupted;
1183         psf->psf_timeout = thread->timeout;
1184         psf->psf_state = thread->state;
1185         psf->psf_wait_data = thread->data;
1186         psf->psf_wakeup_time = thread->wakeup_time;
1187 }
1188
1189 void
1190 _thr_signal_init(void)
1191 {
1192         struct sigaction act;
1193         __siginfohandler_t *sigfunc;
1194         int i;
1195         sigset_t sigset;
1196
1197         SIGFILLSET(sigset);
1198         __sys_sigprocmask(SIG_SETMASK, &sigset, &_thr_initial->sigmask);
1199         /* Enter a loop to get the existing signal status: */
1200         for (i = 1; i <= _SIG_MAXSIG; i++) {
1201                 /* Check for signals which cannot be trapped: */
1202                 if (i == SIGKILL || i == SIGSTOP) {
1203                 }
1204
1205                 /* Get the signal handler details: */
1206                 else if (__sys_sigaction(i, NULL,
1207                             &_thread_sigact[i - 1]) != 0) {
1208                         /*
1209                          * Abort this process if signal
1210                          * initialisation fails:
1211                          */
1212                         PANIC("Cannot read signal handler info");
1213                 }
1214                 /* Intall wrapper if handler was set */
1215                 sigfunc = _thread_sigact[i - 1].sa_sigaction;
1216                 if (((__sighandler_t *)sigfunc) != SIG_DFL &&
1217                     ((__sighandler_t *)sigfunc) != SIG_IGN) {
1218                         act = _thread_sigact[i - 1];
1219                         act.sa_flags |= SA_SIGINFO;
1220                         act.sa_sigaction =
1221                                 (__siginfohandler_t *)_thr_sig_handler;
1222                         __sys_sigaction(i, &act, NULL);
1223                 }
1224         }
1225         /*
1226          * Install the signal handler for SIGINFO.  It isn't
1227          * really needed, but it is nice to have for debugging
1228          * purposes.
1229          */
1230         _thread_sigact[SIGINFO - 1].sa_flags = SA_SIGINFO | SA_RESTART;
1231         SIGEMPTYSET(act.sa_mask);
1232         act.sa_flags = SA_SIGINFO | SA_RESTART;
1233         act.sa_sigaction = (__siginfohandler_t *)&_thr_sig_handler;
1234         if (__sys_sigaction(SIGINFO, &act, NULL) != 0) {
1235                 __sys_sigprocmask(SIG_SETMASK, &_thr_initial->sigmask, NULL);
1236                 /*
1237                  * Abort this process if signal initialisation fails:
1238                  */
1239                 PANIC("Cannot initialize signal handler");
1240         }
1241         __sys_sigprocmask(SIG_SETMASK, &_thr_initial->sigmask, NULL);
1242         __sys_sigaltstack(NULL, &_thr_initial->sigstk);
1243 }
1244
1245 void
1246 _thr_signal_deinit(void)
1247 {
1248         int i;
1249         struct pthread *curthread = _get_curthread();
1250
1251         /* Enter a loop to get the existing signal status: */
1252         for (i = 1; i <= _SIG_MAXSIG; i++) {
1253                 /* Check for signals which cannot be trapped: */
1254                 if (i == SIGKILL || i == SIGSTOP) {
1255                 }
1256
1257                 /* Set the signal handler details: */
1258                 else if (__sys_sigaction(i, &_thread_sigact[i - 1],
1259                          NULL) != 0) {
1260                         /*
1261                          * Abort this process if signal
1262                          * initialisation fails:
1263                          */
1264                         PANIC("Cannot set signal handler info");
1265                 }
1266         }
1267         __sys_sigaltstack(&curthread->sigstk, NULL);
1268 }
1269