/* $Header: /plroot/cuts/1.0/.RCS/PL/src/lib/RCS/set_usig.c,v 1.9 2000/03/28 18:15:48 alaffin Exp $ */ /* * (c) Copyright Cray Research, Inc. Unpublished Proprietary Information. * All Rights Reserved. */ /***************************************************************************** Unicos Testing - Cray Research, Inc. Mendota Heights, Minnesota FUNCTION IDENTIFIER : set_usig Set up for unexpected signals. AUTHOR : Bob Clark CO-PILOT : Dave Baumgartner DATE STARTED : 11/04/86 This module may be linked with c-modules requiring unexpected signal handling. The parameters to set_usig are as follows: fork_flag - set to FORK or NOFORK depending upon whether the calling program executes a fork() system call. It is normally the case that the calling program treats SIGCLD as an expected signal if fork() is being used. handler - a pointer to the unexpected signal handler to be executed after an unexpected signal has been detected. If handler is set to DEF_HANDLER, a default handler is used. This routine should be declared as function returning an int. cleanup - a pointer to a cleanup routine to be executed by the unexpected signal handler before tt_exit is called. This parameter is set to NULL if no cleanup routine is required. An external variable, T_cleanup is set so that other user-defined handlers have access to the cleanup routine. This routine should be declared as returning type void. ***************************************************************************/ #include #include #include #include "test.h" #define MAXMESG 150 /* size of mesg string sent to t_result */ void (*T_cleanup)(); /* pointer to cleanup function */ extern int errno; /**************************************************************************** * set_usig() : set-up to catch unexpected signals. fork_flag is set to NOFORK * if SIGCLD is to be an "unexpected signal", otherwise it is set to * FORK. cleanup points to a cleanup routine to be executed before * tt_exit is called (cleanup is set to NULL if no cleanup is desired). * handler is a pointer to the signal handling routine (if handler is * set to NULL, a default handler is used). ***************************************************************************/ static void def_handler(int sig); /* default signal handler */ void set_usig(fork_flag, handler, cleanup) int fork_flag; /* FORK if SIGCLD is expected, NOFORK if unexpected */ void (*handler)(); /* pointer to signal handler routine or DEF_HANDLER */ void (*cleanup)(); /* pointer to cleanup routine or NULL */ { extern char *Tcid; /* test case id string (in calling prog) */ char mesg[MAXMESG]; /* message buffer for t_result */ int sig; /* * save T_cleanup and handler function pointers */ T_cleanup = cleanup; /* used by default handler */ if (handler == DEF_HANDLER) { /* use default handler */ handler = def_handler; } /* * now loop through all signals and set the handlers */ for (sig = 1; sig < NSIG; sig++) { /* * SIGKILL is never unexpected. * SIGCLD is only unexpected when * no forking is being done. * SIGINFO is used for file quotas and should be expected * SIGCONT cannot be ignored * SIGSTOP will produce an EINVAL error */ switch(sig) { case SIGKILL: /* case SIGINFO: We need to find out what signal we're getting */ case SIGSTOP: case SIGCONT: #if SIGRECOVERY case SIGRECOVERY: /* allow chkpnt/restart */ #endif #ifdef SIGSWAP case SIGSWAP: #endif /* SIGSWAP */ #ifdef SIGCKPT case SIGCKPT: #endif #ifdef SIGRESTART case SIGRESTART: #endif /* * pthread-private signals SIGPTINTR and SIGPTRESCHED. * Setting a handler for these signals is disallowed when * the binary is linked against libpthread. */ #ifdef SIGPTINTR case SIGPTINTR: #endif /* SIGPTINTR */ #ifdef SIGPTRESCHED case SIGPTRESCHED: #endif /* SIGPTRESCHED */ break; /* skip signal handler setup */ case SIGCLD: if ( fork_flag == FORK ) continue; default: if (signal(sig, handler) == SIG_ERR) { (void) sprintf(mesg, "signal() failed for signal %d. error:%d %s.", sig, errno, strerror(errno)); t_result(Tcid, 0, TWARN, mesg); } } } /* endfor */ } /**************************************************************************** * def_handler() : default signal handler that is invoked when * an unexpected signal is caught. ***************************************************************************/ static void def_handler(sig) int sig; /* signal that caused the interrupt */ { extern int T_count; /* number of items completed (in t_result.c) */ extern int T_total; /* total number of test items (in calling prog) */ extern char *Tcid; /* test case id string (in calling prog) */ char mesg[MAXMESG]; /* holds t_result message */ /* first reset trap for this signal (except SIGCLD - its weird) */ if (sig != SIGCLD) { if (signal(sig, def_handler) == SIG_ERR) { (void) sprintf(mesg, "def_handler: signal() failed for signal %d. error:%d %s.", sig, errno, strerror(errno)); t_result(Tcid, 0, TWARN, mesg); } } (void) sprintf(mesg, "Unexpected signal %d received.", sig); /* * call t_result with the second parameter set to * -(number of items to break) */ t_result(Tcid, (T_count - T_total), TBROK, mesg); /* now cleanup and exit */ if (T_cleanup) { (*T_cleanup)(); } tt_exit(); }