Recipe 16.20 Blocking Signals
16.20.1 Problem
You'd like to delay the reception of a
signal, possibly to prevent unpredictable behavior from signals that
can interrupt your program at any point.
16.20.2 Solution
Use the POSIX module's interface to the
sigprocmask(2) syscall. This is available only
if your system is POSIX conformant.
To block a signal around an operation:
use POSIX qw(:signal_h);
$sigset = POSIX::SigSet->new(SIGINT); # define the signals to block
$old_sigset = POSIX::SigSet->new; # where the old sigmask will be kept
sigprocmask(SIG_BLOCK, $sigset, $old_sigset)
or die "Could not block SIGINT\n";
To unblock:
defined sigprocmask(SIG_UNBLOCK, $old_sigset)
or die "Could not unblock SIGINT\n";
16.20.3 Discussion
The POSIX standard introduced sigaction and
sigprocmask to give you better control over how
signals are delivered. The sigprocmask function
controls delayed delivery of signals, and
sigaction installs handlers. If available, Perl
uses sigaction when you change
%SIG.
To use sigprocmask, first build a signal set using
POSIX::SigSet->new. This takes a list of signal
numbers. The POSIX module exports functions named after the signals,
which return their signal numbers.
use POSIX qw(:signal_h);
$sigset = POSIX::SigSet->new( SIGINT, SIGKILL );
Pass the POSIX::SigSet object to sigprocmask with
the SIG_BLOCK flag to delay signal delivery, SIG_UNBLOCK to restore
delivery of the signals, or SIG_SETMASK to block only signals in the
POSIX::SigSet. The most paranoid of programmers block signals for a
fork to prevent a signal handler in the child
process being called before Perl can update the child's
$$ variable, its process id. If the signal handler
were called immediately and reported $$ in that
handler, it could possibly report its parent's $$,
not its own. This issue does not arise often.
16.20.4 See Also
Your system's sigprocmask(2) manpage (if you
have one); the documentation for the standard POSIX module in Chapter
32 of Programming Perl
|