1 /* 2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of version 2 of the GNU General Public License as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it would be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 * 12 * Further, this software is distributed without any warranty that it is 13 * free of the rightful claim of any third person regarding infringement 14 * or the like. Any license provided herein, whether implied or 15 * otherwise, applies only to this software file. Patent licenses, if 16 * any, provided herein do not apply to combinations of this program with 17 * other software, or any other product whatsoever. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write the Free Software Foundation, Inc., 21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 24 * Mountain View, CA 94043, or: 25 * 26 * http://www.sgi.com 27 * 28 * For further information regarding this notice, see: 29 * 30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ 31 */ 32 33 /* $Id: tst_sig.c,v 1.13 2009/08/28 09:29:01 vapier Exp $ */ 34 35 /***************************************************************************** 36 OS Testing - Silicon Graphics, Inc. 37 38 FUNCTION IDENTIFIER : tst_sig Set up for unexpected signals. 39 40 AUTHOR : David D. Fenner 41 42 CO-PILOT : Bill Roske 43 44 DATE STARTED : 06/06/90 45 46 This module may be linked with c-modules requiring unexpected 47 signal handling. The parameters to tst_sig are as follows: 48 49 fork_flag - set to FORK or NOFORK depending upon whether the 50 calling program executes a fork() system call. It 51 is normally the case that the calling program treats 52 SIGCLD as an expected signal if fork() is being used. 53 54 handler - a pointer to the unexpected signal handler to 55 be executed after an unexpected signal has been 56 detected. If handler is set to DEF_HANDLER, a 57 default handler is used. This routine should be 58 declared as function returning an int. 59 60 cleanup - a pointer to a cleanup routine to be executed 61 by the unexpected signal handler before tst_exit is 62 called. This parameter is set to NULL if no cleanup 63 routine is required. An external variable, T_cleanup 64 is set so that other user-defined handlers have 65 access to the cleanup routine. This routine should be 66 declared as returning type void. 67 68 ***************************************************************************/ 69 70 #include <errno.h> 71 #include <string.h> 72 #include <signal.h> 73 #include <unistd.h> 74 #include "test.h" 75 76 #define MAXMESG 150 /* size of mesg string sent to tst_res */ 77 78 static void (*T_cleanup) (); 79 80 static void def_handler(); /* default signal handler */ 81 static void (*tst_setup_signal(int, void (*)(int))) (int); 82 83 /**************************************************************************** 84 * tst_sig() : set-up to catch unexpected signals. fork_flag is set to NOFORK 85 * if SIGCLD is to be an "unexpected signal", otherwise it is set to 86 * FORK. cleanup points to a cleanup routine to be executed before 87 * tst_exit is called (cleanup is set to NULL if no cleanup is desired). 88 * handler is a pointer to the signal handling routine (if handler is 89 * set to NULL, a default handler is used). 90 ***************************************************************************/ 91 92 void tst_sig(int fork_flag, void (*handler) (), void (*cleanup) ()) 93 { 94 int sig; 95 #ifdef _SC_SIGRT_MIN 96 long sigrtmin, sigrtmax; 97 #endif 98 99 /* 100 * save T_cleanup and handler function pointers 101 */ 102 T_cleanup = cleanup; /* used by default handler */ 103 104 if (handler == DEF_HANDLER) { 105 /* use default handler */ 106 handler = def_handler; 107 } 108 #ifdef _SC_SIGRT_MIN 109 sigrtmin = sysconf(_SC_SIGRT_MIN); 110 sigrtmax = sysconf(_SC_SIGRT_MAX); 111 #endif 112 113 /* 114 * now loop through all signals and set the handlers 115 */ 116 117 for (sig = 1; sig < NSIG; sig++) { 118 /* 119 * SIGKILL is never unexpected. 120 * SIGCLD is only unexpected when 121 * no forking is being done. 122 * SIGINFO is used for file quotas and should be expected 123 */ 124 125 #ifdef _SC_SIGRT_MIN 126 if (sig >= sigrtmin && sig <= sigrtmax) 127 continue; 128 #endif 129 130 switch (sig) { 131 case SIGKILL: 132 case SIGSTOP: 133 case SIGCONT: 134 #if !defined(_SC_SIGRT_MIN) && defined(__SIGRTMIN) && defined(__SIGRTMAX) 135 /* Ignore all real-time signals */ 136 case __SIGRTMIN: 137 case __SIGRTMIN + 1: 138 case __SIGRTMIN + 2: 139 case __SIGRTMIN + 3: 140 case __SIGRTMIN + 4: 141 case __SIGRTMIN + 5: 142 case __SIGRTMIN + 6: 143 case __SIGRTMIN + 7: 144 case __SIGRTMIN + 8: 145 case __SIGRTMIN + 9: 146 case __SIGRTMIN + 10: 147 case __SIGRTMIN + 11: 148 case __SIGRTMIN + 12: 149 case __SIGRTMIN + 13: 150 case __SIGRTMIN + 14: 151 case __SIGRTMIN + 15: 152 /* __SIGRTMIN is 37 on HPPA rather than 32 * 153 * as on i386, etc. */ 154 #if !defined(__hppa__) 155 case __SIGRTMAX - 15: 156 case __SIGRTMAX - 14: 157 case __SIGRTMAX - 13: 158 case __SIGRTMAX - 12: 159 case __SIGRTMAX - 11: 160 #endif 161 case __SIGRTMAX - 10: 162 case __SIGRTMAX - 9: 163 case __SIGRTMAX - 8: 164 case __SIGRTMAX - 7: 165 case __SIGRTMAX - 6: 166 case __SIGRTMAX - 5: 167 case __SIGRTMAX - 4: 168 case __SIGRTMAX - 3: 169 case __SIGRTMAX - 2: 170 case __SIGRTMAX - 1: 171 case __SIGRTMAX: 172 #endif 173 #ifdef SIGSWAP 174 case SIGSWAP: 175 #endif /* SIGSWAP */ 176 177 #ifdef SIGCKPT 178 case SIGCKPT: 179 #endif 180 #ifdef SIGRESTART 181 case SIGRESTART: 182 #endif 183 /* 184 * pthread-private signals SIGPTINTR and SIGPTRESCHED. 185 * Setting a handler for these signals is disallowed when 186 * the binary is linked against libpthread. 187 */ 188 #ifdef SIGPTINTR 189 case SIGPTINTR: 190 #endif /* SIGPTINTR */ 191 #ifdef SIGPTRESCHED 192 case SIGPTRESCHED: 193 #endif /* SIGPTRESCHED */ 194 #ifdef _SIGRESERVE 195 case _SIGRESERVE: 196 #endif 197 #ifdef _SIGDIL 198 case _SIGDIL: 199 #endif 200 #ifdef _SIGCANCEL 201 case _SIGCANCEL: 202 #endif 203 #ifdef _SIGGFAULT 204 case _SIGGFAULT: 205 #endif 206 break; 207 208 case SIGCLD: 209 if (fork_flag == FORK) 210 continue; 211 212 default: 213 if (tst_setup_signal(sig, handler) == SIG_ERR) 214 tst_resm(TWARN | TERRNO, 215 "signal failed for signal %d", sig); 216 break; 217 } 218 } 219 } 220 221 /**************************************************************************** 222 * def_handler() : default signal handler that is invoked when 223 * an unexpected signal is caught. 224 ***************************************************************************/ 225 226 static void def_handler(int sig) 227 { 228 /* 229 * Break remaining test cases, do any cleanup, then exit 230 */ 231 tst_brkm(TBROK, T_cleanup, 232 "unexpected signal %s(%d) received (pid = %d).", 233 tst_strsig(sig), sig, getpid()); 234 } 235 236 /* 237 * tst_setup_signal - A function like signal(), but we have 238 * control over its personality. 239 */ 240 static void (*tst_setup_signal(int sig, void (*handler) (int))) (int) { 241 struct sigaction my_act, old_act; 242 int ret; 243 244 my_act.sa_handler = handler; 245 my_act.sa_flags = SA_RESTART; 246 sigemptyset(&my_act.sa_mask); 247 248 ret = sigaction(sig, &my_act, &old_act); 249 250 if (ret == 0) 251 return old_act.sa_handler; 252 else 253 return SIG_ERR; 254 } 255