Operating System‎ > ‎Linux‎ > ‎Linux Shell Script‎ > ‎

08. Processes and Signals (Part 2)

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

Sending Signals

  • 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

Receiving Signals

  • 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.

Signal Handling

  • To ignore or handle the signal, use the trap command in your script
  • Format:
trap   ‘commands to handle signal’   signal_name
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

Special commands to handle signals:

  • 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.