14.6 Sending and Receiving SignalsOne method of interprocess communication is to send and receive signals. A signal is a one-bit message (meaning "this signal happened") sent to a process from another process or from the kernel. Signals are numbered, usually from one to some small number like 15 or 31. Some signals have predefined meanings and are sent automatically to a process under certain conditions (such as memory faults or floating-point exceptions); others are strictly user-generated from other processes. Those processes must have permission to send such a signal. Only if you are the superuser or if the sending process has the same user ID as the receiving process is the signal permitted. The response to a signal is called the signal's action . Predefined signals have certain useful default actions, such as aborting the process or suspending it. Other signals are completely ignored by default. Nearly all signals can have their default action overridden, to either be ignored or else caught (invoking a user-specified section of code automatically). So far, this is all standard stuff; here's where it gets Perl-specific. When a Perl process catches a signal, a subroutine of your choosing gets invoked asynchronously and automatically, momentarily interrupting whatever was executing. When the subroutine exits, whatever was executing resumes as if nothing had happened (except for the actions performed by the subroutine, if any). Typically, the signal-catching subroutine will do one of two things: abort the program after executing some cleanup code, or set some flag (such as a global variable) that the program routinely checks.[ 6 ]
You need to know the signal names to register a signal handler with Perl. By registering a signal handler, Perl will call the selected subroutine when the signal is received.
Signal names are defined in the
signal
(2) manpage, and usually also in the C include file
/usr/include/sys/signal.h
. Names generally start with $SIG{'INT'} = 'my_sigint_catcher'; But we also need a definition for that subroutine. Here's a simple one: sub my_sigint_catcher { $saw_sigint = 1; # set a flag }
This signal catcher sets a global variable and then returns immediately. Returning from this subroutine causes execution to resume wherever it was interrupted. Typically, you'd first zero the $saw_sigint = 0; # clear the flag $SIG{'INT'} = 'my_sigint_catcher'; # register the catcher foreach (@huge_array) { # do something # do more things # do still more things if ($saw_sigint) { # interrupt wanted? # some sort of cleanup here last; } } $SIG{'INT'} = 'DEFAULT'; # restore the default action
The trick here is that the value of the flag is checked at useful points during the evaluation and is used to exit the loop prematurely, here also handling some cleanup actions. Note the last statement in the preceding code: setting the action to
One of the ways that the kill(2,234,237); # send SIGINT to 234 and 237 kill ('INT', 234, 237); #same For more about signal handling, see Chapter 6 of Programming Perl or the perlipc (1) manpage. |
|