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 SIGCHLD 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#include "lapi/signal.h" 76 77#define MAXMESG 150 /* size of mesg string sent to tst_res */ 78 79static void (*T_cleanup) (); 80 81static void def_handler(); /* default signal handler */ 82static void (*tst_setup_signal(int, void (*)(int))) (int); 83 84/**************************************************************************** 85 * tst_sig() : set-up to catch unexpected signals. fork_flag is set to NOFORK 86 * if SIGCHLD is to be an "unexpected signal", otherwise it is set to 87 * FORK. cleanup points to a cleanup routine to be executed before 88 * tst_exit is called (cleanup is set to NULL if no cleanup is desired). 89 * handler is a pointer to the signal handling routine (if handler is 90 * set to NULL, a default handler is used). 91 ***************************************************************************/ 92 93void tst_sig(int fork_flag, void (*handler) (), void (*cleanup) ()) 94{ 95 int sig; 96#ifdef _SC_SIGRT_MIN 97 long sigrtmin, sigrtmax; 98#endif 99 100 /* 101 * save T_cleanup and handler function pointers 102 */ 103 T_cleanup = cleanup; /* used by default handler */ 104 105 if (handler == DEF_HANDLER) { 106 /* use default handler */ 107 handler = def_handler; 108 } 109#ifdef _SC_SIGRT_MIN 110 sigrtmin = sysconf(_SC_SIGRT_MIN); 111 sigrtmax = sysconf(_SC_SIGRT_MAX); 112#endif 113 114 /* 115 * now loop through all signals and set the handlers 116 */ 117 118 for (sig = 1; sig < NSIG; sig++) { 119 /* 120 * SIGKILL is never unexpected. 121 * SIGCHLD is only unexpected when 122 * no forking is being done. 123 * SIGINFO is used for file quotas and should be expected 124 */ 125 126#ifdef _SC_SIGRT_MIN 127 if (sig >= sigrtmin && sig <= sigrtmax) 128 continue; 129#endif 130 131 switch (sig) { 132 case SIGKILL: 133 case SIGSTOP: 134 case SIGCONT: 135#if !defined(_SC_SIGRT_MIN) && defined(__SIGRTMIN) && defined(__SIGRTMAX) 136 /* Ignore all real-time signals */ 137 case __SIGRTMIN: 138 case __SIGRTMIN + 1: 139 case __SIGRTMIN + 2: 140 case __SIGRTMIN + 3: 141 case __SIGRTMIN + 4: 142 case __SIGRTMIN + 5: 143 case __SIGRTMIN + 6: 144 case __SIGRTMIN + 7: 145 case __SIGRTMIN + 8: 146 case __SIGRTMIN + 9: 147 case __SIGRTMIN + 10: 148 case __SIGRTMIN + 11: 149 case __SIGRTMIN + 12: 150 case __SIGRTMIN + 13: 151 case __SIGRTMIN + 14: 152 case __SIGRTMIN + 15: 153/* __SIGRTMIN is 37 on HPPA rather than 32 * 154 * as on i386, etc. */ 155#if !defined(__hppa__) 156 case __SIGRTMAX - 15: 157 case __SIGRTMAX - 14: 158 case __SIGRTMAX - 13: 159 case __SIGRTMAX - 12: 160 case __SIGRTMAX - 11: 161#endif 162 case __SIGRTMAX - 10: 163 case __SIGRTMAX - 9: 164 case __SIGRTMAX - 8: 165 case __SIGRTMAX - 7: 166 case __SIGRTMAX - 6: 167 case __SIGRTMAX - 5: 168 case __SIGRTMAX - 4: 169 case __SIGRTMAX - 3: 170 case __SIGRTMAX - 2: 171 case __SIGRTMAX - 1: 172 case __SIGRTMAX: 173#endif 174#ifdef SIGSWAP 175 case SIGSWAP: 176#endif /* SIGSWAP */ 177 178#ifdef SIGCKPT 179 case SIGCKPT: 180#endif 181#ifdef SIGRESTART 182 case SIGRESTART: 183#endif 184 /* 185 * pthread-private signals SIGPTINTR and SIGPTRESCHED. 186 * Setting a handler for these signals is disallowed when 187 * the binary is linked against libpthread. 188 */ 189#ifdef SIGPTINTR 190 case SIGPTINTR: 191#endif /* SIGPTINTR */ 192#ifdef SIGPTRESCHED 193 case SIGPTRESCHED: 194#endif /* SIGPTRESCHED */ 195#ifdef _SIGRESERVE 196 case _SIGRESERVE: 197#endif 198#ifdef _SIGDIL 199 case _SIGDIL: 200#endif 201#ifdef _SIGCANCEL 202 case _SIGCANCEL: 203#endif 204#ifdef _SIGGFAULT 205 case _SIGGFAULT: 206#endif 207 break; 208 209 case SIGCHLD: 210 if (fork_flag == FORK) 211 continue; 212 213 default: 214 if (tst_setup_signal(sig, handler) == SIG_ERR) 215 tst_resm(TWARN | TERRNO, 216 "signal failed for signal %d", sig); 217 break; 218 } 219 } 220} 221 222/**************************************************************************** 223 * def_handler() : default signal handler that is invoked when 224 * an unexpected signal is caught. 225 ***************************************************************************/ 226 227static void def_handler(int sig) 228{ 229 /* 230 * Break remaining test cases, do any cleanup, then exit 231 */ 232 tst_brkm(TBROK, T_cleanup, 233 "unexpected signal %s(%d) received (pid = %d).", 234 tst_strsig(sig), sig, getpid()); 235} 236 237/* 238 * tst_setup_signal - A function like signal(), but we have 239 * control over its personality. 240 */ 241static void (*tst_setup_signal(int sig, void (*handler) (int))) (int) { 242 struct sigaction my_act, old_act; 243 int ret; 244 245 my_act.sa_handler = handler; 246 my_act.sa_flags = SA_RESTART; 247 sigemptyset(&my_act.sa_mask); 248 249 ret = sigaction(sig, &my_act, &old_act); 250 251 if (ret == 0) 252 return old_act.sa_handler; 253 else 254 return SIG_ERR; 255} 256