Update perlipc.pod for new signals
Nick Ing-Simmons [Sun, 26 May 2002 08:07:12 +0000 (08:07 +0000)]
p4raw-id: //depot/perlio@16794

pod/perlipc.pod

index 80364b9..3535db4 100644 (file)
@@ -19,12 +19,7 @@ triggered automatically by the kernel when special events transpire, like
 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;
@@ -34,6 +29,12 @@ handler could in theory trigger a memory fault and subsequent core dump.
     $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
@@ -214,10 +215,10 @@ to find out whether anyone (or anything) has accidentally removed our fifo.
        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
@@ -225,21 +226,70 @@ core dump.  Second, Perl isn't itself re-entrant at the lowest levels.
 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
 
@@ -511,7 +561,7 @@ in the SEE ALSO section below.
 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
@@ -547,7 +597,7 @@ handles to STDIN and STDOUT and call other processes.
        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
@@ -1488,7 +1538,7 @@ little else within a handler beyond setting a numeric variable that
 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