a child process exiting, your process running out of stack space, or
hitting file size limit.
-For example, to trap an interrupt signal, set up a handler like this.
-Do as little as you possibly can in your handler; notice how all we do is
-set a global variable and then raise an exception. That's because on most
-systems, libraries are not re-entrant; particularly, memory allocation and
-I/O routines are not. That means that doing nearly I<anything> in your
-handler could in theory trigger a memory fault and subsequent core dump.
+For example, to trap an interrupt signal, set up a handler like this:
sub catch_zap {
my $signame = shift;
$SIG{INT} = 'catch_zap'; # could fail in modules
$SIG{INT} = \&catch_zap; # best strategy
+Prior to perl5.7.3 it was necessary to do as little as you possibly can in your handler;
+notice how all we do is set a global variable and then raise an exception. That's because on
+most systems, libraries are not re-entrant; particularly, memory allocation and I/O
+routines are not. That meant that doing nearly I<anything> in your handler could in theory
+trigger a memory fault and subsequent core dump - see L<Deferred Signals> below.
+
The names of the signals are the ones listed out by C<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
sleep 2; # to avoid dup signals
}
-=head2 WARNING
+=head2 Deferred Signals
-By installing Perl code to deal with signals, you're exposing yourself
-to danger from two things. First, few system library functions are
+In perls before perl5.7.3 by installing Perl code to deal with signals, you were exposing
+yourself to danger from two things. First, few system library functions are
re-entrant. If the signal interrupts while Perl is executing one function
(like malloc(3) or printf(3)), and your signal handler then calls the
same function again, you could get unpredictable behavior--often, a
If the signal interrupts Perl while Perl is changing its own internal
data structures, similarly unpredictable behaviour may result.
-There are two things you can do, knowing this: be paranoid or be
-pragmatic. The paranoid approach is to do as little as possible in your
+There were two things you could do, knowing this: be paranoid or be
+pragmatic. The paranoid approach was to do as little as possible in your
signal handler. Set an existing integer variable that already has a
value, and return. This doesn't help you if you're in a slow system call,
which will just restart. That means you have to C<die> to longjump(3) out
of the handler. Even this is a little cavalier for the true paranoiac,
who avoids C<die> in a handler because the system I<is> out to get you.
-The pragmatic approach is to say ``I know the risks, but prefer the
-convenience'', and to do anything you want in your signal handler,
-prepared to clean up core dumps now and again.
+The pragmatic approach was to say ``I know the risks, but prefer the
+convenience'', and to do anything you wanted in your signal handler,
+and be prepared to clean up core dumps now and again.
+
+In perl5.7.3 and later to avoid these problems signals are "deferred" - that is when the
+signal is delivered to the process by the system (to the C code that implements perl) a flag
+is set, and the handler returns immediately. Then at strategic "safe" points in the perl
+interpreter (e.g. when it is about to execute a new opcode) the flags are checked
+and the perl level handler from %SIG is executed. The "deferred" scheme allows much more
+flexibility in the coding of signal handler as we know perl interpreter is in a
+safe state, and that we are not in a system library function when the handler is called.
+However the implementation does differ from previous perls in the following ways:
-To forbid signal handlers altogether would bars you from
-many interesting programs, including virtually everything in this manpage,
-since you could no longer even write SIGCHLD handlers.
+=over 4
+=item Long running opcodes
+
+As perl interpreter only looks at the signal flags when it about to execute a new
+opcode if a signal arrives during a long running opcode (e.g. a regular expression
+operation on a very large string) then signal will not be seen until operation completes.
+
+=item Interrupting IO
+
+When a signal is delivered (e.g. INT control-C) the operating system breaks into
+IO operations like C<read> (used to implement perls E<lt>E<gt> operator). On
+older perls the handler was called immediately (and as C<read> is not "unsafe" this
+worked well). With the "deferred" scheme the handler is not called immediately,
+and if perl is using system's C<stdio> library that library may re-start the C<read>
+without returning to perl and giving it a chance to call the %SIG handler. If this
+happens on your system the solution is to use C<:perlio> layer to do IO - at least
+on those handles which you want to be able to break into with signals. (The C<:perlio>
+layer checks the signal flags and calls %SIG handlers before resuming IO operation.)
+
+=item Signals as "faults"
+
+Certain signals e.g. SEGV, ILL, BUS are generated as a result of virtual memory or
+other "faults". These are normally fatal and there is little a perl-level handler
+can do with them. (In particular the old signal scheme was particularly unsafe
+in such cases.) However if a %SIG handler is set the new scheme simply sets a flag
+and returns as described above. This may cause the operating system to try the
+offending machine instruction again and - as nothing has changed - it will generate
+the signal again. The result of this is a rather odd "loop". In future perl's signal
+mechanism may be changed to avoid this - perhaps by simply disallowing %SIG handlers
+on signals of that type. Until then the work-round is not to set a %SIG handler on
+those signals. (Which signals they are is operating system dependant.)
+
+=item Signals triggered by operating system state
+
+On some operating systems certain signal handlers are supposed to "do something"
+before returning. One example can be CHLD or CLD which indicates a child process
+has completed. On some operating systems the signal handler is expected to C<wait>
+for the completed child process. On such systems the deferred signal scheme will
+not work for those signals (it does not do the C<wait>). Again the failure will
+look like a loop as the operating system will re-issue the signal as there are
+un-waited-for completed child processes.
+
+=back 4
=head1 Using open() for IPC
The newer Expect.pm module from CPAN also addresses this kind of thing.
This module requires two other modules from CPAN: IO::Pty and IO::Stty.
It sets up a pseudo-terminal to interact with programs that insist on
-using talking to the terminal device driver. If your system is
+using talking to the terminal device driver. If your system is
amongst those supported, this may be your best bet.
=head2 Bidirectional Communication with Yourself
exit;
}
-But you don't actually have to make two pipe calls. If you
+But you don't actually have to make two pipe calls. If you
have the socketpair() system call, it will do this all for you.
#!/usr/bin/perl -w
already exists; or, if locked into a slow (restarting) system call,
using die() to raise an exception and longjmp(3) out. In fact, even
these may in some cases cause a core dump. It's probably best to avoid
-signals except where they are absolutely inevitable. This
+signals except where they are absolutely inevitable. This
will be addressed in a future release of Perl.
=head1 AUTHOR