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