- C handles exceptions at the very lowest level, through signals.
- Whenever something goes wrong in a process (you divide by zero,
the user control-Cs, the user kill -9s the process, etc.), the
process is sent a signal. Signals are also used to notify processes of
more "normal" events like keyboard presses and i/o activity.
- Every process has a table which tells the operating system how it
feels about every signal (i.e., the process' disposition towards that
signal). Every process comes with this table set to certain default
dispositions: to exit when a control-C or divide by zero signal is sent, for
example.
- Here is a list of signals and the default dispositions:
Name Value Default Event
SIGHUP 1 Exit Hangup (see termio(7))
SIGINT 2 Exit Interrupt (control-c)
SIGQUIT 3 Core Quit (control-|)
SIGILL 4 Core Illegal Instruction
SIGTRAP 5 Core Trace/Breakpoint Trap
SIGABRT 6 Core Abort
SIGEMT 7 Core Emulation Trap
SIGFPE 8 Core Arithmetic Exception
SIGKILL 9 Exit Killed
SIGBUS 10 Core Bus Error
SIGSEGV 11 Core Segmentation Fault
SIGSYS 12 Core Bad System Call
SIGPIPE 13 Exit Broken Pipe
SIGALRM 14 Exit Alarm Clock
SIGTERM 15 Exit Terminated
SIGUSR1 16 Exit User Signal 1
SIGUSR2 17 Exit User Signal 2
SIGCHLD 18 Ignore Child Status Changed
SIGPWR 19 Ignore Power Fail/Restart
SIGWINCH 20 Ignore Window Size Change
SIGURG 21 Ignore Urgent Socket Condition
SIGPOLL 22 Exit Pollable Event (see streamio(7))
SIGSTOP 23 Stop Stopped (signal)
SIGTSTP 24 Stop Stopped (user) (control-z)
SIGCONT 25 Ignore Continued
SIGTTIN 26 Stop Stopped (tty input) (see termio(7))
SIGTTOU 27 Stop Stopped (tty output) (see termio(7))
SIGVTALRM 28 Exit Virtual Timer Expired
SIGPROF 29 Exit Profiling Timer Expired
SIGXCPU 30 Core CPU time limit exceeded (see
getrlimit(2))
SIGXFSZ 31 Core File size limit exceeded (see
getrlimit(2))
SIGWAITING 32 Ignore Process's LWPs are blocked
SIGLWP 33 Ignore Special signal used by thread library
SIGRTMIN * Exit First real time signal
(SIGRTMIN+1) * Exit Second real time signal
...
(SIGRTMAX-1) * Exit Second-to-last real time signal
SIGRTMAX * Exit Last real time signal
Exit and ignore should be self explanatory. Core means to exit and
dump core, while stop means to temperarily stop execution (as if the
user typed control-Z). Stopped processes can be continued by sending
them the continue signal (SIGCONT), or by placing them in the foreground
(using fg).
- You can use signal or sigset to change your
program's signal dispositions. They are both defined in
signal.h as
void (*signal (int sig, void (*disp)(int)))(int);
void (*sigset (int sig, void (*disp)(int)))(int);
sig is the signal number. disp can be either
- SIG_DFL: do the default action when passed the signal,
- SIG_IGN: ignore the signal,
- a pointer to a routine which takes an int and returns
void. This routine becomes the new signal handler
that gets called whenever the signal is raised.
Both signal and sigset return the old signal handler on
success and SIG_ERR on failure (like if you try to override
SIGKILL or SIGSTOP).
They differ in what happens if while the signal handler is handling a
signal, the same signal is sent again. If you called signal,
the new signal is ignored, while if you called sigset the new
signal is placed on hold and is re-sent when the signal handler is
finished.
- Here's an example:
#include<signal.h>
void myfpeh(int i)
{
/* i is the signal number. Here it should always be SIGFPE,
but theoretically I could install the same signal handler to
handle several different signals. */
printf( "Floating point error. Don't do it again.\n" );
}
int main()
{
int i;
signal( SIGINT, SIG_DFL );
printf( "Can't control-c me now!!\n" );
sigset( SIGFPE, myfpeh );
i = 0 / 0 / 0 / 0 / 0 / 0;
}
- You can also use kill to send signals to processes.
kill comes in two versions: a shell command, and a C function.
Here is the shell command:
athena% ps
PID TTY TIME COMD
24612 pts/11 0:01 tcsh
24663 pts/11 1:31 badprogram
24745 pts/11 0:00 ps
athena% kill -l
HUP INT QUIT ILL TRAP ABRT EMT FPE KILL BUS SEGV SYS PIPE ALRM TERM USR1 USR2
CHLD LOST WINCH URG IO STOP TSTP CONT TTIN TTOU VTALRM PROF XCPU XFSZ WAITING
LWP
athena% kill -KILL 24663
athena% ps
PID TTY TIME COMD
24612 pts/11 0:01 tcsh
24749 pts/11 0:00 ps
athena%
and here is the C function:
#include<sys/types.h>
#include<signal.h>
#include<unistd.h>
int main()
{
/* send myself a seg fault */
kill( getpid(), SIGSEGV );
}