thr_sig.c revision 22315
1/* 2 * Copyright (c) 1995 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 REGENTS 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 */ 33#include <signal.h> 34#include <fcntl.h> 35#include <unistd.h> 36#include <errno.h> 37#ifdef _THREAD_SAFE 38#include <pthread.h> 39#include "pthread_private.h" 40 41void 42_thread_sig_handler(int sig, int code, struct sigcontext * scp) 43{ 44 char c; 45 int i; 46 pthread_t pthread; 47 48 /* 49 * Check if the pthread kernel has unblocked signals (or is about to) 50 * and was on its way into a _thread_sys_select when the current 51 * signal interrupted it: 52 */ 53 if (_thread_kern_in_select) { 54 /* Cast the signal number to a character variable: */ 55 c = sig; 56 57 /* 58 * Write the signal number to the kernel pipe so that it will 59 * be ready to read when this signal handler returns. This 60 * means that the _thread_sys_select call will complete 61 * immediately. 62 */ 63 if (_thread_sys_write(_thread_kern_pipe[1], &c, 1) != 1) { 64 } 65 } 66 /* Check if the signal requires a dump of thread information: */ 67 if (sig == SIGINFO) { 68 /* Dump thread information to file: */ 69 _thread_dump_info(); 70 } else { 71 /* Handle depending on signal type: */ 72 switch (sig) { 73 /* Interval timer used for timeslicing: */ 74 case SIGVTALRM: 75 /* 76 * Don't add the signal to any thread. Just want to 77 * call the scheduler: 78 */ 79 break; 80 81 /* Child termination: */ 82 case SIGCHLD: 83 /* 84 * Enter a loop to process each thread in the linked 85 * list: 86 */ 87 for (pthread = _thread_link_list; pthread != NULL; 88 pthread = pthread->nxt) { 89 /* 90 * Add the signal to the set of pending 91 * signals: 92 */ 93 pthread->sigpend[sig] += 1; 94 if (pthread->state == PS_WAIT_WAIT) { 95 /* Reset the error: */ 96 /* There should be another flag so that this is not required! ### */ 97 _thread_seterrno(pthread, 0); 98 99 /* Change the state of the thread to run: */ 100 PTHREAD_NEW_STATE(pthread,PS_RUNNING); 101 } 102 } 103 104 /* 105 * Go through the file list and set all files 106 * to non-blocking again in case the child 107 * set some of them to block. Sigh. 108 */ 109 for (i = 0; i < _thread_dtablesize; i++) { 110 /* Check if this file is used: */ 111 if (_thread_fd_table[i] != NULL) { 112 /* Set the file descriptor to non-blocking: */ 113 _thread_sys_fcntl(i, F_SETFL, _thread_fd_table[i]->flags | O_NONBLOCK); 114 } 115 } 116 break; 117 118 /* Signals specific to the running thread: */ 119 case SIGBUS: 120 case SIGEMT: 121 case SIGFPE: 122 case SIGILL: 123 case SIGPIPE: 124 case SIGSEGV: 125 case SIGSYS: 126 /* Add the signal to the set of pending signals: */ 127 _thread_run->sigpend[sig] += 1; 128 break; 129 130 /* Signals to send to all threads: */ 131 default: 132 /* 133 * Enter a loop to process each thread in the linked 134 * list: 135 */ 136 for (pthread = _thread_link_list; pthread != NULL; 137 pthread = pthread->nxt) { 138 /* 139 * Add the signal to the set of pending 140 * signals: 141 */ 142 pthread->sigpend[sig] += 1; 143 } 144 break; 145 } 146 147 /* Check if the kernel is not locked: */ 148 if (_thread_run != &_thread_kern_thread) { 149 /* 150 * Schedule the next thread. This function is not 151 * expected to return because it will do a longjmp 152 * instead. 153 */ 154 _thread_kern_sched(scp); 155 156 /* 157 * This point should not be reached, so abort the 158 * process: 159 */ 160 PANIC("Returned to signal function from scheduler"); 161 } 162 } 163 164 /* Returns nothing. */ 165 return; 166} 167#endif 168