This contains links to information used in the lectures. Note that the code segments have less than and greater than replaced by < and > so that they display correctly.
There are differences in signal handling between Berkeley (SunOS 4.2.1) like systems and System V (HP-UX) like systems
Name Number Notes Meaning ______________________________________________________________________ SIGHUP 01 A hangup SIGINT 02 A interrupt SIGQUIT 03 A,B quit SIGILL 04 A,B,C illegal instruction SIGTRAP 05 A,B,C trace trap SIGABRT 06 A,B software generated abort; see abort(3C) SIGIOT 06 A,B software generated signal SIGEMT 07 A,B software generated signal SIGFPE 08 A,B floating point exception SIGKILL 09 A,D,E,F kill SIGBUS 10 A,B bus error SIGSEGV 11 A,B segmentation violation SIGSYS 12 A,B bad argument to system call SIGPIPE 13 A write on a pipe with no one to read it SIGALRM 14 A alarm clock; see alarm(2) SIGTERM 15 A software termination signal SIGUSR1 16 A user defined signal 1 SIGUSR2 17 A user defined signal 2 SIGCHLD l8 G death of a child (see WARNINGS below) SIGCLD l8 G death of a child (see WARNINGS below) SIGPWR 19 C,G power fail (see WARNINGS below) SIGVTALRM 20 A virtual timer alarm; see getitimer(2) SIGPROF 21 A profiling timer alarm; see getitimer(2) SIGIO 22 G asynchronous I/O signal; see select(2) SIGWINCH 23 G window size change; see termio(7) SIGSTOP 24 D,E,H stop SIGTSTP 25 H stop signal generated from keyboard SIGCONT 26 F,G continue after stop SIGTTIN 27 H background read attempted from control terminal SIGTTOU 28 H background write attempted to control terminal SIGURG 29 G urgent data arrived on an I/O channel SIGLOST 30 A file lock lost (NFS file locking) The letters in the Notes column in the table above indicate the action taken when the signal is received, and any special conditions on its use: A The default action is to terminate the process. B The default action of terminating the process also generates a core image file if possible. C The action is not reset to SIG_DFL before calling the signal-catching function. D The signal cannot be ignored. E The signal cannot be caught. F The signal will not be held off from a stopped process. G The default action is to ignore the signal. H The default action is to stop the process.Note that SIGKILL and SIGSTOP cannot be caught or ignored.
stty signal default standard ---------------------------------------- intr SIGINT DEL(Rubout) ^C quit SIGQUIT FS (^|) ^\ susp SIGTSTP (disabled) ^Z dsusp SIGCONT - ^@Aside: The default for erase is # and for kill is @ (not ^U). This is why using these in passwords is a bad idea.
signal(SIGINT,SIG_IGN);
. The signal will be ignored
until the process resets the action.
#include <signal.h> main() { signal(SIGINT, SIG_IGN); /* * pause() just suspends the process until a * signal is received. */ pause(); }
void handler(sig, code, scp, addr) int sig, code; struct sigcontext *scp; char *addr;Here sig is the signal number; code is a parameter of certain signals that provides additional detail; scp is a pointer to the sigcontext structure (defined in <signal.h>), used to restore the context from before the signal; and addr is additional address information.
#include <signal.h> main() { /* * Declare handler routine so we can use its name. */ extern int handler(); /* * Send signal to handler routine. */ signal(SIGINT, handler); /* * Loop here. */ for (;;) pause(); } /* * handler--handle the signal. */ handler() { /* * Users of 4.2 and 4.3BSD systems should un-comment * this line, which will make this program * behave as if it were on a non-Berkeley system. */ /* signal(SIGINT, SIG_DFL); */ printf("OUCH\n"); }
#include <signal.h> main() { /* * Declare handler routine so we can use its * name. */ extern int handler(); /* * Send signal to handler routine. */ signal(SIGINT, handler); /* * Loop here. */ for (;;) pause(); } /* * handler--handle the signal. */ handler() { /* * Users of 4.2 and 4.3BSD systems should un-comment * this line, which will make this program * behave as if it were on a non-Berkeley system. */ /* signal(SIGINT, SIG_DFL); */ printf("OUCH\n"); /* * Reset the signal to come here again. */ signal(SIGINT, handler); }
#include <signal.h> main() { /* * Declare handler routine so we can use its * name. */ extern int handler(); /* * Send signal to handler routine. Only do so * if the signal is not already being ignored. */ if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, handler); /* * Loop here. */ for (;;) pause(); } /* * handler--handle the signal. sig is the signal * number which interrupted us. */ handler(sig) int sig; { /* * Users of 4.2 and 4.3BSD systems should un-comment * this line, which will make this program * behave as if it were on a non-Berkeley * system (we reset the signal by hand). */ /* signal(sig, SIG_DFL); */ /* * Ignore the signal for the duration of this * routine. */ signal(sig, SIG_IGN); printf("OUCH\n"); /* * Reset the signal to come here again. */ signal(SIGINT, handler); }
void (*sa_handler)(); sigset_t sa_mask; int sa_flags;
#include <stdio.h> #include <signal.h> #include <errno.h> #include <unistd.h> /* */ /* */ /*SYNOPSIS */ /* #include <signal.h> */ /* */ /* int sigaction ( */ /* int sig, signal to watch */ /* const struct sigaction *act, action to take */ /* struct sigaction *oact old action */ /* ); */ /* struct { */ /* void (*sa_handler)(); { SIG_DFL,SIG_IGN,address} */ /* sigset_t sa_mask; */ /* int sa_flags; */ /* } sigaction */ int counter,was_siged=0; pid_t mypid; void myhandler1(int sig, int code, struct sigcontext *spc); void myhandler2(int sig, int code, struct sigcontext *spc); void myhandler3(int sig, int code, struct sigcontext *spc); main (int argc, char * argv[]) { struct sigaction act,oact; sigset_t myset,oldset,pset; mypid = getpid(); printf ("Starting process %d \n",mypid); act.sa_handler = SIG_IGN; /* Do not need to set the mask in act.sa_mask, since it is only used if signals are caught */ if (sigaction(SIGHUP,&act,&oact)) { perror("Could not set signal handler.\n"); } act.sa_handler = &myhandler1; /* Fill the mask in act.sa_mask */ sigfillset(&(act.sa_mask)); /* Install myhandler1 as handler for SIGUSR2 and block all signals during handling */ if (sigaction(SIGUSR2,&act,&oact)) { perror("Could not set signal handler.\n"); } act.sa_handler = &myhandler2; if (sigaction(SIGINT,&act,&oact)) { perror("Could not set signal handler. \n"); } /* this is a section of code where I don't want any signals */ sigfillset(&myset); /* Set mask to myset which is full to block all signals - store original mask in oldset */ sigprocmask(SIG_SETMASK,&myset,&oldset); /* do the critical stuff */ printf ("I'm gonna take a nap go away. \n"); sleep(5); printf ("That was a nice nap. I'm back.\n"); /* Store the pending signals in pset */ sigpending(&pset); /* Test if SIGINT is one of the pending signals - if so set the handler to myhandler3, reset the mask to unblock SIGINT. If SIGINT occured it will be handled now by myhandler3. */ if (sigismember(&pset,SIGINT)) { act.sa_handler = &myhandler3; if (sigaction(SIGINT,&act,&oact)) { perror("Could not set signal handler.\n"); } sigdelset(&myset,SIGINT); sigprocmask(SIG_SETMASK,&myset,NULL); } /* Restore the old action for SIGINT and reset the mask to the old mask */ if (sigaction(SIGINT,&oact,NULL)) { perror("Could not set signal handler.\n"); } sigprocmask(SIG_SETMASK,&oldset,NULL); /* end of critical section */ printf ("Setting the counter to 0 \n"); counter = 0; while (1) { if (was_siged) { printf("Signal processed, counter : %d\n",counter); was_siged = 0; } counter++; } } void myhandler1(int sig, int code, struct sigcontext *spc) { static int count=0; printf("Caught the SIGUSR2 signal %d COUNTER is: %d \n",sig,counter); /* First time it gets called, it calls itself to show the effect of recieving a SIGUSR2 while processing a SIGUSR2 */ if (count == 0) { count++; printf ("Calling kill with sig SIGUSR2 \n"); kill(mypid,SIGUSR2); printf ("Done Calling kill with sig SIGUSR2 \n"); } was_siged = 1; } void myhandler2(int sig, int code, struct sigcontext *spc) { printf("Caught the SIGINT signal %d COUNTER is: %d \n",sig,counter); exit(0); } void myhandler3(int sig, int code, struct sigcontext *spc) { printf("You typed ^C while I was sleeping, GO AWAY.\n",sig,counter); }
An example of handling signals in Perl.
#!/usr/local/bin/perl sub handler{ local ($signal) = @_; print "The $signal was caught \n"; $SIG{'USR1'} = 'handler'; } # the signal array is an associative array %SIG print "The process id is $$\n"; # ignore the HUP signal $SIG{'HUP'} = 'IGNORE'; # set the action for SIGBUS to default. $SIG{'BUS'} = 'DEFAULT'; # set usr1 handler to be handler. $SIG{'USR1'} = 'handler'; while (1) { $count++; }
An example of handling signals in sh.
#!/bin/sh echo "the pid is $$" # trap [cmd list] signal trap "echo a sigusr1 was typed" 16 # trap [cmd list] 0 will execute when the shell is exited. trap "echo so long and thanks for all the fish" 0 1 echo "Here is a list of commands associated with the signals" trap #trap "echo the man page says this causes an error " 11 i=1 while true do i=`expr $i + 1` done
#include <signal.h> #include <setjmp.h> /* * The environment for setjmp. */ jmp_buf env; main() { int i; char buf[16]; extern int timeout(); /* * Inform the system we want to catch the * alarm signal. */ signal(SIGALRM, timeout); /* * The code inside the if gets executed the first * time through setjmp, - recall setjmp returns 0 * the code inside the else gets executed the second time * when the lonjmp causes execution to continue as if * the setjmp had returned the value given as the second argument * to longjmp (in this case 1) */ if (setjmp(env) == 0) { /* * Issue a request for an alarm to be * delivered in 15 seconds. */ alarm(15); /* * Prompt for input. */ printf("Type a word; if you don't in 15 "); printf("seconds I'll use \"WORD\": "); gets(buf); /* * Turn off the alarm. */ alarm(0); } else { /* * Assume the default. */ strcpy(buf, "WORD"); } printf("\nThe word is: %s\n", buf); exit(0); } /* * timeout--catch the signal. */ timeout(sig) int sig; { /* * Ignore the signal for the duration of this * routine. */ signal(sig, SIG_IGN); /* * We would perform any timeout-related * functions here; in this case there * are none. */ /* * Restore the action of the alarm signal. */ signal(SIGALRM, timeout); /* * Return to the main routine at setjmp, * and make setjmp return 1. */ longjmp(env, 1); }