CSc 352 Signal Handling in Unix Saumya Debray Dept. of Computer Science The University of Arizona, Tucson debray@cs.arizona.edu Signals • A signal is a mechanism for notifying a program that some event has occurred. – intuition: signal “software interrupt” – when a signal is sent to a program, its normal execution is interrupted – depending on (1) the state of the program, and (2) the type of signal, the program may • enter some pre-specified signal handler; or • take some default action. 2 Example Signals Signal Name SIGHUP SIGINT SIGQUIT SIGILL SIGTRAP SIGFPE SIGKILL SIGSEGV SIGTERM SIGSTKFLT SIGSTOP SIGPROF SIGWINCH SIGPWR … Number 1 2 3 4 5 8 9 11 15 16 19 27 28 30 … (not a complete list) Description Hangup (POSIX) Terminal interrupt (ANSI) Terminal quit (POSIX) Illegal instruction (ANSI) Trace trap (POSIX) Floating point exception (ANSI) Kill(can't be caught or ignored) (POSIX) Invalid memory segment access (ANSI) Termination (ANSI) Stack fault Stop executing(can't be caught or ignored) (POSIX) Profiling alarm clock (4.2 BSD) Window size change (4.3 BSD, Sun) Power failure restart (System V) … 3 Synchronous vs. Asynchronous Signals • Synchronous signals: – arise from executing an instruction in the process’s instruction stream • e.g.: illegal instruction (SIGILL); illegal address (SIGSEGV) – causes a trap into the OS kernel trap handler • sometimes referred to as “traps” – directed to the process/thread that executed the instruction • Asynchronous signals: – source is external to the current execution • e.g.: profiling clock (SIGPROF); terminal interrupt, ^C (SIGINT) 4 What’s going on: A high-level view • Signal sending: processes – OS kernel updates info for destination process • Signal receiving: – kernel forces target process to handle signal • Pending signals are sent but not yet received • A process can block some signals signals Operating system kernel interrupts devices 5 Dealing with Signals • The way in which a process deals with a given signal is called the disposition of that signal in that process. • Possible dispositions: – ignore – default • different for different signals – programmer-specified handler • Exceptions: SIGKILL and SIGSTOP – defaults cannot be changed for these 6 Specifying a Signal Handler 7 Specifying a Signal Handler changes the signal handler 8 Specifying a Signal Handler signal number (can’t be SIGKILL or SIGSTOP) 9 Specifying a Signal Handler info about new handler) 10 Specifying a Signal Handler if non-NULL, where to save old handler info 11 Specifying a Signal Handler pointer to handler function: void handler(int signal_num) or SIG_DFL or SIG_IGN 12 Specifying a Signal Handler specifies handler if sa_flags contains SA_SIGINFO 13 Specifying a Signal Handler specifies signals that should be blocked while the handler is executing 14 A Simple Example structure to hold info about handler 15 A Simple Example signal handler function 16 A Simple Example specifying the handler 17 A Simple Example didn’t change the default signal handler NULL pointer dereference produces a Segmentation fault 18 A Simple Example signal handler changed but why does it get executed over and over? 19 Behind the scenes of a SIGSEGV • When a program tries to access a bad address: – execution traps into the OS kernel – if no handler is specified: • kernel invokes the default handler • default handler prints out “Segmentation fault” and kills the process – if a handler is specified: • kernel executes the handler – the expectation is that the handler fixes the problem • restarts the offending operation – this allows programmer-controlled recovery from errors 20 Another Example: weird factorial no base case??? 21 weird factorial: cont’d y-1 j = x i=0 = x*y 22 weird factorial: cont’d j = 1 * 2 * … * n = n! 23 weird factorial: cont’d signal handler for SIGSEGV (signal raised by dereferencing a bad pointer in factorial() ) prints out k = n! and exits sets k = n! 24 Sending signals • A program can send a signal to another program using the kill() system call: int kill(pid_t pid, int sig) sends the signal number sig to process pid (see /usr/include/asm-generic/signal.h) • A user can send a signal from the command line using the kill command: kill –N pid E.g., “kill -9 pid” (9 = SIGKILL) 25 Asynchronous signals SIGINT will be handled by my_handler() send SIGINT to process with process-id = target 26 Asynchronous signals – cont’d 27 Blocking signals • Each process has a list (bit-vector) of blocked signals – when a signal is blocked, it remains pending • Related system calls: – sigprocmask(2) system call changes the list of blocked signals – sigpending(2) shows which signals are (blocked and) pending – sigsuspend(2) suspends the calling process until the specified signal is received 28 Signal voodoo • When a process forks off a child, it may want to hear back about how things went – when the child process exits, it becomes a zombie until its exit status is reported to the parent process – when something interesting happens to the child (it exits, crashes, stops, etc.), a SIGCHLD signal is sent to its parent – the parent can use the wait() system call (or variants) to find the child’s exit status • If the parent is not interested, it can use sigaction() to explicitly specify that SIGCHLD should be ignored 29