thr_sig.c revision 102590
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 102590 2002-08-29 23:06:07Z deischen $ 33 */ 34#include <sys/param.h> 35#include <sys/types.h> 36#include <sys/signalvar.h> 37#include <signal.h> 38#include <fcntl.h> 39#include <unistd.h> 40#include <setjmp.h> 41#include <errno.h> 42#include <pthread.h> 43#include "pthread_private.h" 44 45/* Prototypes: */ 46static void thread_sig_add(struct pthread *pthread, int sig, int has_args); 47static void thread_sig_check_state(struct pthread *pthread, int sig); 48static struct pthread *thread_sig_find(int sig); 49static void thread_sig_handle_special(int sig); 50static void thread_sigframe_add(struct pthread *thread, int sig, 51 int has_args); 52static void thread_sigframe_save(struct pthread *thread, 53 struct pthread_signal_frame *psf); 54static void thread_sig_invoke_handler(int sig, siginfo_t *info, 55 ucontext_t *ucp); 56 57/*#define DEBUG_SIGNAL*/ 58#ifdef DEBUG_SIGNAL 59#define DBG_MSG stdout_debug 60#else 61#define DBG_MSG(x...) 62#endif 63 64#if defined(_PTHREADS_INVARIANTS) 65#define SIG_SET_ACTIVE() _sig_in_handler = 1 66#define SIG_SET_INACTIVE() _sig_in_handler = 0 67#else 68#define SIG_SET_ACTIVE() 69#define SIG_SET_INACTIVE() 70#endif 71 72void 73_thread_sig_handler(int sig, siginfo_t *info, ucontext_t *ucp) 74{ 75 struct pthread *curthread = _get_curthread(); 76 struct pthread *pthread, *pthread_h; 77 int in_sched = _thread_kern_in_sched; 78 char c; 79 80 if (ucp == NULL) 81 PANIC("Thread signal handler received null context"); 82 DBG_MSG("Got signal %d, current thread %p\n", sig, curthread); 83 84 /* Check if an interval timer signal: */ 85 if (sig == _SCHED_SIGNAL) { 86 /* Update the scheduling clock: */ 87 gettimeofday((struct timeval *)&_sched_tod, NULL); 88 _sched_ticks++; 89 90 if (in_sched != 0) { 91 /* 92 * The scheduler is already running; ignore this 93 * signal. 94 */ 95 } 96 /* 97 * Check if the scheduler interrupt has come when 98 * the currently running thread has deferred thread 99 * signals. 100 */ 101 else if (curthread->sig_defer_count > 0) 102 curthread->yield_on_sig_undefer = 1; 103 else { 104 /* Schedule the next thread: */ 105 _thread_kern_sched(ucp); 106 107 /* 108 * This point should not be reached, so abort the 109 * process: 110 */ 111 PANIC("Returned to signal function from scheduler"); 112 } 113 } 114 /* 115 * Check if the kernel has been interrupted while the scheduler 116 * is accessing the scheduling queues or if there is a currently 117 * running thread that has deferred signals. 118 */ 119 else if ((in_sched != 0) || (curthread->sig_defer_count > 0)) { 120 /* Cast the signal number to a character variable: */ 121 c = sig; 122 123 /* 124 * Write the signal number to the kernel pipe so that it will 125 * be ready to read when this signal handler returns. 126 */ 127 if (_queue_signals != 0) { 128 __sys_write(_thread_kern_pipe[1], &c, 1); 129 DBG_MSG("Got signal %d, queueing to kernel pipe\n", sig); 130 } 131 if (_thread_sigq[sig - 1].blocked == 0) { 132 DBG_MSG("Got signal %d, adding to _thread_sigq\n", sig); 133 /* 134 * Do not block this signal; it will be blocked 135 * when the pending signals are run down. 136 */ 137 /* _thread_sigq[sig - 1].blocked = 1; */ 138 139 /* 140 * Queue the signal, saving siginfo and sigcontext 141 * (ucontext). 142 * 143 * XXX - Do we need to copy siginfo and ucp? 144 */ 145 _thread_sigq[sig - 1].signo = sig; 146 if (info != NULL) 147 memcpy(&_thread_sigq[sig - 1].siginfo, info, 148 sizeof(*info)); 149 memcpy(&_thread_sigq[sig - 1].uc, ucp, sizeof(*ucp)); 150 151 /* Indicate that there are queued signals: */ 152 _thread_sigq[sig - 1].pending = 1; 153 _sigq_check_reqd = 1; 154 } 155 /* These signals need special handling: */ 156 else if (sig == SIGCHLD || sig == SIGTSTP || 157 sig == SIGTTIN || sig == SIGTTOU) { 158 _thread_sigq[sig - 1].pending = 1; 159 _thread_sigq[sig - 1].signo = sig; 160 _sigq_check_reqd = 1; 161 } 162 else 163 DBG_MSG("Got signal %d, ignored.\n", sig); 164 } 165 /* 166 * The signal handlers should have been installed so that they 167 * cannot be interrupted by other signals. 168 */ 169 else if (_thread_sigq[sig - 1].blocked == 0) { 170 /* 171 * The signal is not blocked; handle the signal. 172 * 173 * Ignore subsequent occurrences of this signal 174 * until the current signal is handled: 175 */ 176 _thread_sigq[sig - 1].blocked = 1; 177 178 /* This signal will be handled; clear the pending flag: */ 179 _thread_sigq[sig - 1].pending = 0; 180 181 /* 182 * Save siginfo and sigcontext (ucontext). 183 * 184 * XXX - Do we need to copy siginfo and ucp? 185 */ 186 _thread_sigq[sig - 1].signo = sig; 187 188 if (info != NULL) 189 memcpy(&_thread_sigq[sig - 1].siginfo, info, 190 sizeof(*info)); 191 memcpy(&_thread_sigq[sig - 1].uc, ucp, sizeof(*ucp)); 192 SIG_SET_ACTIVE(); 193 194 /* Handle special signals: */ 195 thread_sig_handle_special(sig); 196 197 pthread_h = NULL; 198 if ((pthread = thread_sig_find(sig)) == NULL) 199 DBG_MSG("No thread to handle signal %d\n", sig); 200 else if (pthread == curthread) { 201 /* 202 * Unblock the signal and restore the process signal 203 * mask in case we don't return from the handler: 204 */ 205 _thread_sigq[sig - 1].blocked = 0; 206 __sys_sigprocmask(SIG_SETMASK, &_process_sigmask, NULL); 207 208 /* Call the signal handler for the current thread: */ 209 thread_sig_invoke_handler(sig, info, ucp); 210 211 /* 212 * Set the process signal mask in the context; it 213 * could have changed by the handler. 214 */ 215 ucp->uc_sigmask = _process_sigmask; 216 217 /* Resume the interrupted thread: */ 218 __sys_sigreturn(ucp); 219 } else { 220 DBG_MSG("Got signal %d, adding frame to thread %p\n", 221 sig, pthread); 222 223 /* Setup the target thread to receive the signal: */ 224 thread_sig_add(pthread, sig, /*has_args*/ 1); 225 226 /* Take a peek at the next ready to run thread: */ 227 pthread_h = PTHREAD_PRIOQ_FIRST(); 228 DBG_MSG("Finished adding frame, head of prio list %p\n", 229 pthread_h); 230 } 231 SIG_SET_INACTIVE(); 232 233 /* 234 * Switch to a different context if the currently running 235 * thread takes a signal, or if another thread takes a 236 * signal and the currently running thread is not in a 237 * signal handler. 238 */ 239 if ((pthread_h != NULL) && 240 (pthread_h->active_priority > curthread->active_priority)) { 241 /* Enter the kernel scheduler: */ 242 _thread_kern_sched(ucp); 243 } 244 } 245 else { 246 SIG_SET_ACTIVE(); 247 thread_sig_handle_special(sig); 248 SIG_SET_INACTIVE(); 249 } 250} 251 252static void 253thread_sig_invoke_handler(int sig, siginfo_t *info, ucontext_t *ucp) 254 { 255 struct pthread *curthread = _get_curthread(); 256 void (*sigfunc)(int, siginfo_t *, void *); 257 int saved_seqno; 258 sigset_t saved_sigmask; 259 260 /* Invoke the signal handler without going through the scheduler: 261 */ 262 DBG_MSG("Got signal %d, calling handler for current thread %p\n", 263 sig, curthread); 264 265 /* Save the threads signal mask: */ 266 saved_sigmask = curthread->sigmask; 267 saved_seqno = curthread->sigmask_seqno; 268 269 /* Setup the threads signal mask: */ 270 SIGSETOR(curthread->sigmask, _thread_sigact[sig - 1].sa_mask); 271 sigaddset(&curthread->sigmask, sig); 272 273 /* 274 * Check that a custom handler is installed and if 275 * the signal is not blocked: 276 */ 277 sigfunc = _thread_sigact[sig - 1].sa_sigaction; 278 if (((__sighandler_t *)sigfunc != SIG_DFL) && 279 ((__sighandler_t *)sigfunc != SIG_IGN)) { 280 if (((_thread_sigact[sig - 1].sa_flags & SA_SIGINFO) != 0) || 281 (info == NULL)) 282 (*(sigfunc))(sig, info, ucp); 283 else 284 (*(sigfunc))(sig, (siginfo_t *)info->si_code, ucp); 285 } 286 /* 287 * Only restore the signal mask if it hasn't been changed by the 288 * application during invocation of the signal handler: 289 */ 290 if (curthread->sigmask_seqno == saved_seqno) 291 curthread->sigmask = saved_sigmask; 292} 293 294/* 295 * Find a thread that can handle the signal. 296 */ 297struct pthread * 298thread_sig_find(int sig) 299{ 300 struct pthread *curthread = _get_curthread(); 301 int handler_installed; 302 struct pthread *pthread, *pthread_next; 303 struct pthread *suspended_thread, *signaled_thread; 304 305 DBG_MSG("Looking for thread to handle signal %d\n", sig); 306 /* Check if the signal requires a dump of thread information: */ 307 if (sig == SIGINFO) { 308 /* Dump thread information to file: */ 309 _thread_dump_info(); 310 311 /* Unblock this signal to allow further dumps: */ 312 _thread_sigq[sig - 1].blocked = 0; 313 } 314 /* Check if an interval timer signal: */ 315 else if (sig == _SCHED_SIGNAL) { 316 /* 317 * This shouldn't ever occur (should this panic?). 318 */ 319 } else { 320 /* 321 * Enter a loop to look for threads that have the signal 322 * unmasked. POSIX specifies that a thread in a sigwait 323 * will get the signal over any other threads. Second 324 * preference will be threads in in a sigsuspend. Third 325 * preference will be the current thread. If none of the 326 * above, then the signal is delivered to the first thread 327 * that is found. Note that if a custom handler is not 328 * installed, the signal only affects threads in sigwait. 329 */ 330 suspended_thread = NULL; 331 if ((curthread != &_thread_kern_thread) && 332 !sigismember(&curthread->sigmask, sig)) 333 signaled_thread = curthread; 334 else 335 signaled_thread = NULL; 336 if ((_thread_sigact[sig - 1].sa_handler == SIG_IGN) || 337 (_thread_sigact[sig - 1].sa_handler == SIG_DFL)) 338 handler_installed = 0; 339 else 340 handler_installed = 1; 341 342 for (pthread = TAILQ_FIRST(&_waitingq); 343 pthread != NULL; pthread = pthread_next) { 344 /* 345 * Grab the next thread before possibly destroying 346 * the link entry. 347 */ 348 pthread_next = TAILQ_NEXT(pthread, pqe); 349 350 if ((pthread->state == PS_SIGWAIT) && 351 sigismember(pthread->data.sigwait, sig)) { 352 /* Change the state of the thread to run: */ 353 PTHREAD_NEW_STATE(pthread,PS_RUNNING); 354 /* 355 * A signal handler is not invoked for threads 356 * in sigwait. Clear the blocked and pending 357 * flags. 358 */ 359 _thread_sigq[sig - 1].blocked = 0; 360 _thread_sigq[sig - 1].pending = 0; 361 362 /* Return the signal number: */ 363 pthread->signo = sig; 364 365 /* 366 * POSIX doesn't doesn't specify which thread 367 * will get the signal if there are multiple 368 * waiters, so we give it to the first thread 369 * we find. 370 * 371 * Do not attempt to deliver this signal 372 * to other threads and do not add the signal 373 * to the process pending set. 374 */ 375 return (NULL); 376 } 377 else if ((handler_installed != 0) && 378 !sigismember(&pthread->sigmask, sig) && 379 ((pthread->flags & PTHREAD_FLAGS_SUSPENDED) == 0)) { 380 if (pthread->state == PS_SIGSUSPEND) { 381 if (suspended_thread == NULL) 382 suspended_thread = pthread; 383 } else if (signaled_thread == NULL) 384 signaled_thread = pthread; 385 } 386 } 387 388 /* 389 * Only perform wakeups and signal delivery if there is a 390 * custom handler installed: 391 */ 392 if (handler_installed == 0) { 393 /* 394 * There is no handler installed. Unblock the 395 * signal so that if a handler _is_ installed, any 396 * subsequent signals can be handled. 397 */ 398 _thread_sigq[sig - 1].blocked = 0; 399 } else { 400 /* 401 * If we didn't find a thread in the waiting queue, 402 * check the all threads queue: 403 */ 404 if (suspended_thread == NULL && 405 signaled_thread == NULL) { 406 /* 407 * Enter a loop to look for other threads 408 * capable of receiving the signal: 409 */ 410 TAILQ_FOREACH(pthread, &_thread_list, tle) { 411 if (!sigismember(&pthread->sigmask, 412 sig)) { 413 signaled_thread = pthread; 414 break; 415 } 416 } 417 } 418 419 if (suspended_thread == NULL && 420 signaled_thread == NULL) 421 /* 422 * Add it to the set of signals pending 423 * on the process: 424 */ 425 sigaddset(&_process_sigpending, sig); 426 else { 427 /* 428 * We only deliver the signal to one thread; 429 * give preference to the suspended thread: 430 */ 431 if (suspended_thread != NULL) 432 pthread = suspended_thread; 433 else 434 pthread = signaled_thread; 435 return (pthread); 436 } 437 } 438 } 439 440 /* Returns nothing. */ 441 return (NULL); 442} 443 444void 445_thread_sig_check_pending(struct pthread *pthread) 446{ 447 sigset_t sigset; 448 int i; 449 450 /* 451 * Check if there are pending signals for the running 452 * thread or process that aren't blocked: 453 */ 454 sigset = pthread->sigpend; 455 SIGSETOR(sigset, _process_sigpending); 456 SIGSETNAND(sigset, pthread->sigmask); 457 if (SIGNOTEMPTY(sigset)) { 458 for (i = 1; i < NSIG; i++) { 459 if (sigismember(&sigset, i) != 0) { 460 if (sigismember(&pthread->sigpend, i) != 0) 461 thread_sig_add(pthread, i, 462 /*has_args*/ 0); 463 else { 464 thread_sig_add(pthread, i, 465 /*has_args*/ 1); 466 sigdelset(&_process_sigpending, i); 467 } 468 } 469 } 470 } 471} 472 473/* 474 * This can only be called from the kernel scheduler. It assumes that 475 * all thread contexts are saved and that a signal frame can safely be 476 * added to any user thread. 477 */ 478void 479_thread_sig_handle_pending(void) 480{ 481 struct pthread *pthread; 482 int i, sig; 483 484 PTHREAD_ASSERT(_thread_kern_in_sched != 0, 485 "_thread_sig_handle_pending called from outside kernel schedule"); 486 /* 487 * Check the array of pending signals: 488 */ 489 for (i = 0; i < NSIG; i++) { 490 if (_thread_sigq[i].pending != 0) { 491 /* This signal is no longer pending. */ 492 _thread_sigq[i].pending = 0; 493 494 sig = _thread_sigq[i].signo; 495 496 /* Some signals need special handling: */ 497 thread_sig_handle_special(sig); 498 499 if (_thread_sigq[i].blocked == 0) { 500 /* 501 * Block future signals until this one 502 * is handled: 503 */ 504 _thread_sigq[i].blocked = 1; 505 506 if ((pthread = thread_sig_find(sig)) != NULL) { 507 /* 508 * Setup the target thread to receive 509 * the signal: 510 */ 511 thread_sig_add(pthread, sig, 512 /*has_args*/ 1); 513 } 514 } 515 } 516 } 517} 518 519static void 520thread_sig_handle_special(int sig) 521{ 522 struct pthread *pthread, *pthread_next; 523 int i; 524 525 switch (sig) { 526 case SIGCHLD: 527 /* 528 * Go through the file list and set all files 529 * to non-blocking again in case the child 530 * set some of them to block. Sigh. 531 */ 532 for (i = 0; i < _thread_dtablesize; i++) { 533 /* Check if this file is used: */ 534 if (_thread_fd_table[i] != NULL) { 535 /* 536 * Set the file descriptor to non-blocking: 537 */ 538 __sys_fcntl(i, F_SETFL, 539 _thread_fd_getflags(i) | O_NONBLOCK); 540 } 541 } 542 /* 543 * Enter a loop to wake up all threads waiting 544 * for a process to complete: 545 */ 546 for (pthread = TAILQ_FIRST(&_waitingq); 547 pthread != NULL; pthread = pthread_next) { 548 /* 549 * Grab the next thread before possibly 550 * destroying the link entry: 551 */ 552 pthread_next = TAILQ_NEXT(pthread, pqe); 553 554 /* 555 * If this thread is waiting for a child 556 * process to complete, wake it up: 557 */ 558 if (pthread->state == PS_WAIT_WAIT) { 559 /* Make the thread runnable: */ 560 PTHREAD_NEW_STATE(pthread,PS_RUNNING); 561 562 /* Return the signal number: */ 563 pthread->signo = sig; 564 } 565 } 566 break; 567 568 /* 569 * POSIX says that pending SIGCONT signals are 570 * discarded when one of these signals occurs. 571 */ 572 case SIGTSTP: 573 case SIGTTIN: 574 case SIGTTOU: 575 /* 576 * Enter a loop to discard pending SIGCONT 577 * signals: 578 */ 579 TAILQ_FOREACH(pthread, &_thread_list, tle) { 580 sigdelset(&pthread->sigpend, SIGCONT); 581 } 582 break; 583 584 default: 585 break; 586 } 587} 588 589/* 590 * Perform thread specific actions in response to a signal. 591 * This function is only called if there is a handler installed 592 * for the signal, and if the target thread has the signal 593 * unmasked. 594 */ 595static void 596thread_sig_add(struct pthread *pthread, int sig, int has_args) 597{ 598 int restart; 599 int suppress_handler = 0; 600 int thread_is_active = 0; 601 602 restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART; 603 604 /* Make sure this signal isn't still in the pending set: */ 605 sigdelset(&pthread->sigpend, sig); 606 607 /* 608 * Process according to thread state: 609 */ 610 switch (pthread->state) { 611 /* 612 * States which do not change when a signal is trapped: 613 */ 614 case PS_DEAD: 615 case PS_DEADLOCK: 616 case PS_STATE_MAX: 617 case PS_SIGTHREAD: 618 /* 619 * You can't call a signal handler for threads in these 620 * states. 621 */ 622 suppress_handler = 1; 623 break; 624 625 /* 626 * States which do not need any cleanup handling when signals 627 * occur: 628 */ 629 case PS_RUNNING: 630 /* 631 * Remove the thread from the queue before changing its 632 * priority: 633 */ 634 if ((pthread->flags & PTHREAD_FLAGS_IN_PRIOQ) != 0) 635 PTHREAD_PRIOQ_REMOVE(pthread); 636 else 637 /* 638 * This thread is running; avoid placing it in 639 * the run queue: 640 */ 641 thread_is_active = 1; 642 break; 643 644 case PS_SUSPENDED: 645 break; 646 647 case PS_SPINBLOCK: 648 /* Remove the thread from the workq and waitq: */ 649 PTHREAD_WORKQ_REMOVE(pthread); 650 PTHREAD_WAITQ_REMOVE(pthread); 651 /* Make the thread runnable: */ 652 PTHREAD_SET_STATE(pthread, PS_RUNNING); 653 break; 654 655 case PS_SIGWAIT: 656 /* The signal handler is not called for threads in SIGWAIT. */ 657 suppress_handler = 1; 658 /* Wake up the thread if the signal is blocked. */ 659 if (sigismember(pthread->data.sigwait, sig)) { 660 /* Change the state of the thread to run: */ 661 PTHREAD_NEW_STATE(pthread, PS_RUNNING); 662 663 /* Return the signal number: */ 664 pthread->signo = sig; 665 } else 666 /* Increment the pending signal count. */ 667 sigaddset(&pthread->sigpend, sig); 668 break; 669 670 /* 671 * The wait state is a special case due to the handling of 672 * SIGCHLD signals. 673 */ 674 case PS_WAIT_WAIT: 675 if (sig == SIGCHLD) { 676 /* Change the state of the thread to run: */ 677 PTHREAD_WAITQ_REMOVE(pthread); 678 PTHREAD_SET_STATE(pthread, PS_RUNNING); 679 680 /* Return the signal number: */ 681 pthread->signo = sig; 682 } 683 else { 684 /* 685 * Mark the thread as interrupted only if the 686 * restart flag is not set on the signal action: 687 */ 688 if (restart == 0) 689 pthread->interrupted = 1; 690 PTHREAD_WAITQ_REMOVE(pthread); 691 PTHREAD_SET_STATE(pthread, PS_RUNNING); 692 } 693 break; 694 695 /* 696 * States which cannot be interrupted but still require the 697 * signal handler to run: 698 */ 699 case PS_COND_WAIT: 700 case PS_MUTEX_WAIT: 701 /* 702 * Remove the thread from the wait queue. It will 703 * be added back to the wait queue once all signal 704 * handlers have been invoked. 705 */ 706 PTHREAD_WAITQ_REMOVE(pthread); 707 break; 708 709 case PS_JOIN: 710 /* 711 * Remove the thread from the wait queue. It will 712 * be added back to the wait queue once all signal 713 * handlers have been invoked. 714 */ 715 PTHREAD_WAITQ_REMOVE(pthread); 716 /* Make the thread runnable: */ 717 PTHREAD_SET_STATE(pthread, PS_RUNNING); 718 break; 719 720 /* 721 * States which are interruptible but may need to be removed 722 * from queues before any signal handler is called. 723 * 724 * XXX - We may not need to handle this condition, but will 725 * mark it as a potential problem. 726 */ 727 case PS_FDLR_WAIT: 728 case PS_FDLW_WAIT: 729 case PS_FILE_WAIT: 730 if (restart == 0) 731 pthread->interrupted = 1; 732 /* 733 * Remove the thread from the wait queue. Our 734 * signal handler hook will remove this thread 735 * from the fd or file queue before invoking 736 * the actual handler. 737 */ 738 PTHREAD_WAITQ_REMOVE(pthread); 739 break; 740 741 /* 742 * States which are interruptible: 743 */ 744 case PS_FDR_WAIT: 745 case PS_FDW_WAIT: 746 if (restart == 0) { 747 /* 748 * Flag the operation as interrupted and 749 * set the state to running: 750 */ 751 pthread->interrupted = 1; 752 PTHREAD_SET_STATE(pthread, PS_RUNNING); 753 } 754 PTHREAD_WORKQ_REMOVE(pthread); 755 PTHREAD_WAITQ_REMOVE(pthread); 756 break; 757 758 case PS_POLL_WAIT: 759 case PS_SELECT_WAIT: 760 case PS_SLEEP_WAIT: 761 /* 762 * Unmasked signals always cause poll, select, and sleep 763 * to terminate early, regardless of SA_RESTART: 764 */ 765 pthread->interrupted = 1; 766 /* Remove threads in poll and select from the workq: */ 767 if ((pthread->flags & PTHREAD_FLAGS_IN_WORKQ) != 0) 768 PTHREAD_WORKQ_REMOVE(pthread); 769 PTHREAD_WAITQ_REMOVE(pthread); 770 PTHREAD_SET_STATE(pthread, PS_RUNNING); 771 break; 772 773 case PS_SIGSUSPEND: 774 PTHREAD_WAITQ_REMOVE(pthread); 775 PTHREAD_SET_STATE(pthread, PS_RUNNING); 776 break; 777 } 778 779 if (suppress_handler == 0) { 780 /* Setup a signal frame and save the current threads state: */ 781 thread_sigframe_add(pthread, sig, has_args); 782 783 /* 784 * Signals are deferred until just before the threads 785 * signal handler is invoked: 786 */ 787 pthread->sig_defer_count = 1; 788 789 /* Make sure the thread is runnable: */ 790 if (pthread->state != PS_RUNNING) 791 PTHREAD_SET_STATE(pthread, PS_RUNNING); 792 /* 793 * The thread should be removed from all scheduling 794 * queues at this point. Raise the priority and place 795 * the thread in the run queue. It is also possible 796 * for a signal to be sent to a suspended thread, 797 * mostly via pthread_kill(). If a thread is suspended, 798 * don't insert it into the priority queue; just set 799 * its state to suspended and it will run the signal 800 * handler when it is resumed. 801 */ 802 pthread->active_priority |= PTHREAD_SIGNAL_PRIORITY; 803 if ((pthread->flags & PTHREAD_FLAGS_SUSPENDED) != 0) 804 PTHREAD_SET_STATE(pthread, PS_SUSPENDED); 805 else if (thread_is_active == 0) 806 PTHREAD_PRIOQ_INSERT_TAIL(pthread); 807 } 808} 809 810static void 811thread_sig_check_state(struct pthread *pthread, int sig) 812{ 813 /* 814 * Process according to thread state: 815 */ 816 switch (pthread->state) { 817 /* 818 * States which do not change when a signal is trapped: 819 */ 820 case PS_DEAD: 821 case PS_DEADLOCK: 822 case PS_STATE_MAX: 823 case PS_SIGTHREAD: 824 case PS_RUNNING: 825 case PS_SUSPENDED: 826 case PS_SPINBLOCK: 827 case PS_COND_WAIT: 828 case PS_JOIN: 829 case PS_MUTEX_WAIT: 830 break; 831 832 case PS_SIGWAIT: 833 /* Wake up the thread if the signal is blocked. */ 834 if (sigismember(pthread->data.sigwait, sig)) { 835 /* Change the state of the thread to run: */ 836 PTHREAD_NEW_STATE(pthread, PS_RUNNING); 837 838 /* Return the signal number: */ 839 pthread->signo = sig; 840 } else 841 /* Increment the pending signal count. */ 842 sigaddset(&pthread->sigpend, sig); 843 break; 844 845 /* 846 * The wait state is a special case due to the handling of 847 * SIGCHLD signals. 848 */ 849 case PS_WAIT_WAIT: 850 if (sig == SIGCHLD) { 851 /* 852 * Remove the thread from the wait queue and 853 * make it runnable: 854 */ 855 PTHREAD_NEW_STATE(pthread, PS_RUNNING); 856 857 /* Return the signal number: */ 858 pthread->signo = sig; 859 } 860 break; 861 862 case PS_FDLR_WAIT: 863 case PS_FDLW_WAIT: 864 case PS_SIGSUSPEND: 865 case PS_SLEEP_WAIT: 866 /* 867 * Remove the thread from the wait queue and make it 868 * runnable: 869 */ 870 PTHREAD_NEW_STATE(pthread, PS_RUNNING); 871 872 /* Flag the operation as interrupted: */ 873 pthread->interrupted = 1; 874 break; 875 876 /* 877 * These states are additionally in the work queue: 878 */ 879 case PS_FDR_WAIT: 880 case PS_FDW_WAIT: 881 case PS_FILE_WAIT: 882 case PS_POLL_WAIT: 883 case PS_SELECT_WAIT: 884 /* 885 * Remove the thread from the wait and work queues, and 886 * make it runnable: 887 */ 888 PTHREAD_WORKQ_REMOVE(pthread); 889 PTHREAD_NEW_STATE(pthread, PS_RUNNING); 890 891 /* Flag the operation as interrupted: */ 892 pthread->interrupted = 1; 893 break; 894 } 895} 896 897/* 898 * Send a signal to a specific thread (ala pthread_kill): 899 */ 900void 901_thread_sig_send(struct pthread *pthread, int sig) 902{ 903 struct pthread *curthread = _get_curthread(); 904 905 /* Check for signals whose actions are SIG_DFL: */ 906 if (_thread_sigact[sig - 1].sa_handler == SIG_DFL) { 907 /* 908 * Check to see if a temporary signal handler is 909 * installed for sigwaiters: 910 */ 911 if (_thread_dfl_count[sig] == 0) 912 /* 913 * Deliver the signal to the process if a handler 914 * is not installed: 915 */ 916 kill(getpid(), sig); 917 /* 918 * Assuming we're still running after the above kill(), 919 * make any necessary state changes to the thread: 920 */ 921 thread_sig_check_state(pthread, sig); 922 } 923 /* 924 * Check that the signal is not being ignored: 925 */ 926 else if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) { 927 if (pthread->state == PS_SIGWAIT && 928 sigismember(pthread->data.sigwait, sig)) { 929 /* Change the state of the thread to run: */ 930 PTHREAD_NEW_STATE(pthread, PS_RUNNING); 931 932 /* Return the signal number: */ 933 pthread->signo = sig; 934 } else if (sigismember(&pthread->sigmask, sig)) 935 /* Add the signal to the pending set: */ 936 sigaddset(&pthread->sigpend, sig); 937 else if (pthread == curthread) 938 /* Call the signal handler for the current thread: */ 939 thread_sig_invoke_handler(sig, NULL, NULL); 940 else { 941 /* Protect the scheduling queues: */ 942 _thread_kern_sig_defer(); 943 /* 944 * Perform any state changes due to signal 945 * arrival: 946 */ 947 thread_sig_add(pthread, sig, /* has args */ 0); 948 /* Unprotect the scheduling queues: */ 949 _thread_kern_sig_undefer(); 950 } 951 } 952} 953 954/* 955 * User thread signal handler wrapper. 956 * 957 * thread - current running thread 958 */ 959void 960_thread_sig_wrapper(void) 961{ 962 struct pthread_signal_frame *psf; 963 struct pthread *thread = _get_curthread(); 964 965 /* Get the current frame and state: */ 966 psf = thread->curframe; 967 thread->curframe = NULL; 968 PTHREAD_ASSERT(psf != NULL, "Invalid signal frame in signal handler"); 969 970 /* 971 * We're coming from the kernel scheduler; clear the in 972 * scheduler flag: 973 */ 974 _thread_kern_in_sched = 0; 975 976 /* Check the threads previous state: */ 977 if (psf->saved_state.psd_state != PS_RUNNING) { 978 /* 979 * Do a little cleanup handling for those threads in 980 * queues before calling the signal handler. Signals 981 * for these threads are temporarily blocked until 982 * after cleanup handling. 983 */ 984 switch (psf->saved_state.psd_state) { 985 case PS_FDLR_WAIT: 986 case PS_FDLW_WAIT: 987 _fd_lock_backout(thread); 988 psf->saved_state.psd_state = PS_RUNNING; 989 break; 990 991 case PS_COND_WAIT: 992 _cond_wait_backout(thread); 993 psf->saved_state.psd_state = PS_RUNNING; 994 break; 995 996 case PS_MUTEX_WAIT: 997 _mutex_lock_backout(thread); 998 psf->saved_state.psd_state = PS_RUNNING; 999 break; 1000 1001 default: 1002 break; 1003 } 1004 } 1005 1006 /* Unblock the signal in case we don't return from the handler: */ 1007 _thread_sigq[psf->signo - 1].blocked = 0; 1008 1009 /* 1010 * Lower the priority before calling the handler in case 1011 * it never returns (longjmps back): 1012 */ 1013 thread->active_priority &= ~PTHREAD_SIGNAL_PRIORITY; 1014 1015 /* 1016 * Reenable interruptions without checking for the need to 1017 * context switch: 1018 */ 1019 thread->sig_defer_count = 0; 1020 1021 /* 1022 * Dispatch the signal via the custom signal handler: 1023 */ 1024 if (psf->sig_has_args == 0) 1025 thread_sig_invoke_handler(psf->signo, NULL, NULL); 1026 else 1027 thread_sig_invoke_handler(psf->signo, &psf->siginfo, &psf->uc); 1028 1029 /* 1030 * Call the kernel scheduler to safely restore the frame and 1031 * schedule the next thread: 1032 */ 1033 _thread_kern_sched_frame(psf); 1034} 1035 1036static void 1037thread_sigframe_add(struct pthread *thread, int sig, int has_args) 1038{ 1039 struct pthread_signal_frame *psf = NULL; 1040 unsigned long stackp; 1041 1042 /* Get the top of the threads stack: */ 1043 stackp = GET_STACK_JB(thread->ctx.jb); 1044 1045 /* 1046 * Leave a little space on the stack and round down to the 1047 * nearest aligned word: 1048 */ 1049 stackp -= sizeof(double); 1050 stackp &= ~0x3UL; 1051 1052 /* Allocate room on top of the stack for a new signal frame: */ 1053 stackp -= sizeof(struct pthread_signal_frame); 1054 1055 psf = (struct pthread_signal_frame *) stackp; 1056 1057 /* Save the current context in the signal frame: */ 1058 thread_sigframe_save(thread, psf); 1059 1060 /* Set handler specific information: */ 1061 psf->sig_has_args = has_args; 1062 psf->signo = sig; 1063 if (has_args) { 1064 /* Copy the signal handler arguments to the signal frame: */ 1065 memcpy(&psf->uc, &_thread_sigq[psf->signo - 1].uc, 1066 sizeof(psf->uc)); 1067 memcpy(&psf->siginfo, &_thread_sigq[psf->signo - 1].siginfo, 1068 sizeof(psf->siginfo)); 1069 } 1070 1071 /* Setup the signal mask: */ 1072 SIGSETOR(thread->sigmask, _thread_sigact[sig - 1].sa_mask); 1073 sigaddset(&thread->sigmask, sig); 1074 1075 /* Set up the new frame: */ 1076 thread->curframe = psf; 1077 thread->flags &= PTHREAD_FLAGS_PRIVATE | PTHREAD_FLAGS_TRACE | 1078 PTHREAD_FLAGS_IN_SYNCQ; 1079 /* 1080 * Set up the context: 1081 */ 1082 stackp -= sizeof(double); 1083 _setjmp(thread->ctx.jb); 1084 SET_STACK_JB(thread->ctx.jb, stackp); 1085 SET_RETURN_ADDR_JB(thread->ctx.jb, _thread_sig_wrapper); 1086} 1087 1088void 1089_thread_sigframe_restore(struct pthread *thread, 1090 struct pthread_signal_frame *psf) 1091{ 1092 memcpy(&thread->ctx, &psf->ctx, sizeof(thread->ctx)); 1093 /* 1094 * Only restore the signal mask if it hasn't been changed 1095 * by the application during invocation of the signal handler: 1096 */ 1097 if (thread->sigmask_seqno == psf->saved_state.psd_sigmask_seqno) 1098 thread->sigmask = psf->saved_state.psd_sigmask; 1099 thread->curframe = psf->saved_state.psd_curframe; 1100 thread->wakeup_time = psf->saved_state.psd_wakeup_time; 1101 thread->data = psf->saved_state.psd_wait_data; 1102 thread->state = psf->saved_state.psd_state; 1103 thread->flags = psf->saved_state.psd_flags; 1104 thread->interrupted = psf->saved_state.psd_interrupted; 1105 thread->signo = psf->saved_state.psd_signo; 1106 thread->sig_defer_count = psf->saved_state.psd_sig_defer_count; 1107} 1108 1109static void 1110thread_sigframe_save(struct pthread *thread, struct pthread_signal_frame *psf) 1111{ 1112 memcpy(&psf->ctx, &thread->ctx, sizeof(thread->ctx)); 1113 psf->saved_state.psd_sigmask = thread->sigmask; 1114 psf->saved_state.psd_curframe = thread->curframe; 1115 psf->saved_state.psd_wakeup_time = thread->wakeup_time; 1116 psf->saved_state.psd_wait_data = thread->data; 1117 psf->saved_state.psd_state = thread->state; 1118 psf->saved_state.psd_flags = thread->flags & 1119 (PTHREAD_FLAGS_PRIVATE | PTHREAD_FLAGS_TRACE); 1120 psf->saved_state.psd_interrupted = thread->interrupted; 1121 psf->saved_state.psd_sigmask_seqno = thread->sigmask_seqno; 1122 psf->saved_state.psd_signo = thread->signo; 1123 psf->saved_state.psd_sig_defer_count = thread->sig_defer_count; 1124} 1125 1126