UNIX Power Tools

UNIX Power ToolsSearch this book
Previous: 45.7 The exec Command Chapter 45
Shell Programming for the Initiated
Next: 45.9 The Unappreciated Bourne Shell  ":" Operator
 

45.8 Handling Signals to Child Processes

The Bourne shell trap command (44.12) controls what the shell does when it gets an interrupt or signal (from the kill (38.10) command, from a keyboard character like CTRL-c, and so on). To run an external command (1.10)- like an editor or a simple command such as sort-the shell starts a child process (38.3) (subprocess). If the program running in the child process wants to handle its own signals, the parent shell should probably pass signals on to the child process. For example, you might run vi as a child process and want to send a CTRL-c to stop vi from what it's doing, but not want the CTRL-c to kill the parent shell script.

When the parent process gets a signal, should it die or keep running? Should the child get the signal or not? The Bourne shell gives you a fair amount of flexibility in signal handling. The bad news is that most sh manual pages don't say much about this. And no manual page I've seen explains a useful choice: using the : (colon) operator (45.9) with trap. Table 45.1 shows your choices.

Table 45.1: trap Arguments (for Most Bourne Shells)
ArgumentEffect
""Ignore signal, don't pass signal to child.
:(undocumented) Ignore signal, pass signal to child.
"command-line"

Run command-line with variable and command substitution done when trap set; don't pass signal to child.

'command-line'

Run command-line with variable and command substitution done when trap executed; don't pass signal to child.

No argument

Reset signal handling to default (usually, parent terminates). Pass signal to child.

Because so much of this is undocumented, I won't try to give you "the answers" for how it should work with your shell. Instead, here are two shell scripts that let you experiment with your shell's signal handling. One script, named parent, starts the second script, child. The child script sets some traps, then starts sleep (40.2) so it'll be there when you send a signal. This lets you use CTRL-c or other interrupts, if parent is running in the foreground - or the kill command with signal numbers, if you've put parent in the background. You can edit the trap lines in the two scripts to test the setup you want to use.

Here's an example. I'll start parent in the background from the C shell, then send it a signal 1 ("hangup" signal):




%1 






% parent &
[1] 8669
parent started
child started. pid is 8671
% kill -1 %1
./child: % 8671 Hangup
child got a signal 1
child exiting
parent still running after child exited
	...1000 seconds later...
parent exiting
[1]  + Done                 parent

Now, the scripts:

% cat parent
#!/bin/sh
echo parent started
trap "echo parent exiting; exit" 0
trap : 1                              # pass signal 1 to child but don't die
trap "" 2                             # ignore signal 2, block from child
trap "echo parent got signal 15" 15   # ignore signal 15, send to child
                                      # die on other signals, send to child
child
echo parent still running after child exited
sleep 1000
% cat child
#! /bin/sh
echo child started. pid is $$.
trap 'echo child exiting; exit' 0
trap 'echo child got a signal 1' 1
trap '' 2       # ignore signal 2
trap 'echo child got a signal 3' 3
sleep 1000      # wait a long time for a signal

Even with this help, the way signal handling works might not be too clear. For more on signal handling, see a book that covers UNIX internals on your system.

- JP


Previous: 45.7 The exec Command UNIX Power ToolsNext: 45.9 The Unappreciated Bourne Shell  ":" Operator
45.7 The exec Command Book Index45.9 The Unappreciated Bourne Shell ":" Operator

The UNIX CD Bookshelf NavigationThe UNIX CD BookshelfUNIX Power ToolsUNIX in a NutshellLearning the vi Editorsed & awkLearning the Korn ShellLearning the UNIX Operating System