Processes and Signals
Types of Signals
Every signal has a name starting with SIG and has a positive unique integer assigned to it
To see the list of all signal names and their associated number on a Linux system, run the command: kill –l (option l for list)
Some common signals
SIGHUP: generated when a terminal hangs up. When you disconnect from voyager in the middle of running some process, the shell receives a SIGHUP
SIGINT: generated when control-c is entered on the keyboard. It is used to interrupt the currently running process
SIGQUIT: generated when the you type exit to log out of voyager. It sends a quit message to the voyager server
SIGTSTP: generated when you type control-z to stop (suspend) a process
SIGCONT: generated to continue a process that has been stopped previously
SIGTERM: generated when you type the kill command to terminate a process
SIGKILL and SIGSTOP: Cannot be ignored by the process, it is the absolute way to kill or stop (suspend) a process
As a user at the command line, you can communicate with your running process by sending certain signals to your process
The signals you can send as a user at the command line are typically to stop (suspend) or terminate a running process
[ To send signals to communicate back and forth with a process, you cannot simply do this on the command line. You will need to write a program that will run as a process to handle the communication. This is what system programming is about. ]
At the command line, you can send the following signals to a process that is currently running at the same login terminal:
SIGINT: control-c
SIGTSTP: control-z
SIGCONT: fg
In addition, at a different login terminal, you can also use the kill command to terminate any process that is yours
In default mode, kill will send a SIGTERM: kill pid_num where pid_num is the PID of the process
kill can also be used with the signal name as an option, to send other types of signal
Format: kill –signal_name pid_num
or kill –signal_num pid_num
In order to use the kill command to send a signal to a process running in the foreground, you will need to log in to a second window (terminal)
For example, a script is running in the foreground with PID 23456 at terminal 2. Therefore:
At terminal 2: At a different terminal 3:
control-z equivalent to: kill –SIGTSTP 23456
fg equivalent to: kill –SIGCONT 23456
When a signal is sent to a running process, the process can choose to:
Use the default reaction: the process does not need to do anything. The OS will look up the default signal handling routine and execute it
Ignore the signal: the process has code to ignore the signal, and continues running as if a signal was not sent to it
Handle the signal itself: the process catches the signal, then runs its own instructions for handling the signal
To ignore or handle the signal, the process must catch the signal and then have its own instructions to react to the signal
Note that SIGSTOP and SIGKILL cannot be ignored or handled by the user process
If your script does not have specific instructions to handle signals, then when it receives a signal, the default signal handler will be used
For example, when you type control-c, the default reaction is that your script will terminate
However, you can write extra instructions in the script so that it will ignore the control-c and keep going.
To ignore or handle the signal, use the trap command in your script
Format:
trap ‘commands to handle signal’ signal_name
OR
trap ‘commands to handle signal’ signal_num
where:
commands to handle signal can be no command, or one command, or several commands that are delimited by semicolon, or a function
quotes are needed so that all the commands are sent to trap by the shell as a single argument
signal_name can be without the prefix SIG. A list of space delimited signal names can be used with one trap command
signal_num is the signal number. A list of space delimited signal numbers can be used with one trap command
when a list of signal names or signal numbers is used, then the commands to handle signal apply to all signals in the list
Example: trap ‘echo received kill signal’ TERM
or trap ‘echo received kill signal’ SIGTERM
or trap ‘echo received kill signal’ 15
are all the same signal handling routine, and they do the same actions:
- Upon receiving a SIGTERM, print a message
- Then execution resumes with the next command in the script, instead of terminate as with default SIGTERM handling
Example: trap ‘echo interrupted; exit 1’ 1 2 15
is the same signal handling routine for 3 different types of signals:
- Upon receiving a SIGHUP, SIGINT, or SIGTERM, print a message then exit with code 1
Example: trap ‘hupHandling’ SIGHUP
runs a function called hupHandling to handle SIGHUP
- Upon receiving a SIGHUP, execution jumps to the function hupHandling to run the code in the function
- When hupHandling finishes running, if there is no call to exit in the function, then execution returns back to the current line of code. The return code from a signal handling function is always 0
If there is no command between the quotes, then the signal is ignored
Example: trap ‘ ’ TERM
means ignore SIGTERM if it is received
If there is no command field, then the default handling is restored for the signal
Example: trap TERM
means default handling is restored for SIGTERM
Use only one signal name or number for this case, because you want the specific default to be restored for a signal
This is useful if you want special signal handling for one part of your script, but you want default signal handling for another part.
Final Thoughts
Signal handling is an important part of shell scripting
An interrupted script can leave unpredictable results, such as temporary files that need to be cleaned up, or permissions that are not set properly, or files that are half written
A well written application traps the interrupting signals and cleans up before exiting
Congratulations on reaching the end of the topics for shell scripting, using bash. In the last 2 topics, we will review all the concepts we have covered, but with the Korn and tcsh syntax.