For example, to trap an interrupt signal, set up a handler like this. Notice how all we do is set with a global variable and then raise an exception. That's because on most systems libraries are not re-entrant, so calling any print() functions (or even anything that needs to malloc(3) more memory) could in theory trigger a memory fault and subsequent core dump.
The names of the signals are the ones listed out by kill -l
on your
system, or you can retrieve them from the Config module. Set up an
@signame list indexed by number to get the name and a %signo table
indexed by name to get the number:
So to check whether signal 17 and SIGALRM were the same, just do this:
You may also choose to assign the strings 'IGNORE'
or 'DEFAULT'
as
the handler, in which case Perl will try to discard the signal or do the
default thing. Some signals can be neither trapped nor ignored, such as
the KILL and STOP (but not the TSTP) signals. One strategy for
temporarily ignoring signals is to use a local() statement, which will be
automatically restored once your block is exited. (Remember that local()
values are "inherited" by functions called from within that block.)
Sending a signal to a negative process ID means that you send the signal to the entire Unix process-group. This code send a hang-up signal to all processes in the current process group except for the current process itself:
Another interesting signal to send is signal number zero. This doesn't actually affect another process, but instead checks whether it's alive or has changed its UID.
You might also want to employ anonymous functions for simple signal handlers:
But that will be problematic for the more complicated handlers that need to re-install themselves. Because Perl's signal mechanism is currently based on the signal(3) function from the C library, you may somtimes be so misfortunate as to run on systems where that function is "broken", that is, it behaves in the old unreliable SysV way rather than the newer, more reasonable BSD and POSIX fashion. So you'll see defensive people writing signal handlers like this:
or even the more elaborate:
Signal handling is also used for timeouts in Unix, While safely
protected within an eval{}
block, you set a signal handler to trap
alarm signals and then schedule to have one delivered to you in some
number of seconds. Then try your blocking operation, clearing the alarm
when it's done but not before you've exited your eval{}
block. If it
goes off, you'll use die() to jump out of the block, much as you might
using longjmp() or throw() in other languages.
Here's an example:
For more complex signal handling, you might see the standard POSIX module. Lamentably, this is almost entirely undocumented, but the t/lib/posix.t file from the Perl source distribution has some examples in it.