From: Nick Ing-Simmons Date: Sun, 26 May 2002 08:07:12 +0000 (+0000) Subject: Update perlipc.pod for new signals X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=a11adca011b9f1db181b88d5dc68ab4fdf8c03df;p=p5sagit%2Fp5-mst-13.2.git Update perlipc.pod for new signals p4raw-id: //depot/perlio@16794 --- diff --git a/pod/perlipc.pod b/pod/perlipc.pod index 80364b9..3535db4 100644 --- a/pod/perlipc.pod +++ b/pod/perlipc.pod @@ -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 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 in your handler could in theory +trigger a memory fault and subsequent core dump - see L below. + The names of the signals are the ones listed out by C 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 to longjump(3) out of the handler. Even this is a little cavalier for the true paranoiac, who avoids C in a handler because the system I 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 (used to implement perls EE operator). On +older perls the handler was called immediately (and as C is not "unsafe" this +worked well). With the "deferred" scheme the handler is not called immediately, +and if perl is using system's C library that library may re-start the C +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 +for the completed child process. On such systems the deferred signal scheme will +not work for those signals (it does not do the C). 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