[% setvar title Safe Signals %]
To see what is currently happening visit http://www.perl6.org/
Safe Signals
Maintainer: Uri Guttman <uri@sysarch.com> Date: 7 Aug 2000 Mailing List: perl6-language-flow@perl.org Number: 60 Version: 1 Status: Developing
This RFC describes how Perl6 can support safe signals with multiple techniques.
Perl5 suffers from its well know unsafe signal handling. It is due to the asynchronous way signals are triggered at the level of C code. A signal could be delivered in Perl while some critical operation (e.g. malloc) is happening and all hell breaks loose. Signals have to be delivered synchronously with respect Perl op code dispatching.
There are multiple ways to support safe signals and they can all easily be supported. Here are the most common ways and various techniques which make handling signals easier.
If you have only a single linear thread of code and want safe signals, you have to pay the penalty of checking for them in between Perl op codes. This requires the Perl compiler to insert signal checking op at regular intervals in the op tree. This can be done every N ops with N being some special global value. The code to do the test can be done in-line in the main dispatch loop and be very fast. The actual C handlers will just be like the ones in the event loop and just bump counters and set flags.
Enabling in-line testing for signals can also be a compile time option so a selected section of of a thread could be where the test are inserted.
Here is a possible pragma to enable this:
use signal in-line => 10 ;
Then you can just create callbacks for any signal as shown below.
A mailbox is a combination of a semaphore and a queue/pipe. It is a clean way to send messages between threads. A special mailbox for signals can be created which can be tested and blocked upon. The data read from the mailbox will be the signal name and any other info attached to the signal. Any thread (including a single thread) can synchornously test for signals under program control. This is how a progrom would poll for signals.
Event loops support safe signals by delivering them synchronously with the dispatch of other callbacks. Then the signal callback cannot collide with any others. This is currently being done in Event.pm (and i think Perl/Tk's event loop is similar here).
Threads can work with signals in two ways. First, one or more threads can run event loops and their signal handlers are safe and can do work or communicate with other threads. Second, any thread can block on the special signal mailbox. When the signal is delivered, the blocked thread can continue safely and can then do the work for that signal.
This pragma would use the same callback interface as all the new I/O objects would. This consistancy of callback style in the language is a major win here. Since someone mentioned any default Perl callback names be in caps, will go with that here. Again the default method names would be carefully chosen to be easy to remember and use, e.g. SIGHUP_RECEIVED and SIGHUP_TIMEOUT would be the ones for the above example if the callback value was an object or a class.
By using the general callback API, signals now can have builtin timeouts. This simplifies some tasks which need to do work on a schedule and also when you need it, e.g. checkpointing. If this were triggered by SIGHUP, then it could be set to timeout every minute and the callback would execute if there hasn't seen any HUPs in that period.
I propose a pragma which would make creating signal callback more of a top level operation and remove the need for the %SIG hash. The pragma would be stackable so you could override a handler inside a code block.
It would be something like this:
# Here is a main line code callback with a sub ref and timeout # the timeout will call the sub SIGHUP_TIMEOUT in this current package.
use signal name => 'SIGHUP', cb => \&hup_handler, timeout => 3600 ; sub hup_handler { print "They hupped me! Bastards!!" }
# Here is a class level callback with the default callback name
use signal name => 'SIGINT', cb => __PACKAGE__ ; sub SIGINT_HANDLER { print "They killed me! Bastards!!" }
# Here is a object callback with the a custom callback name
my $foo = Bar->new() ; use signal name => 'SIGCANCEL', cb => $foo, method = 'cancel_handler' ; sub Bar::cancel_handler { print "They cancelled me! Bastards!!" }
People will stop bitching about perl not having safe signals.
Event.pm - XS based event loop module.
RFC #1 - Implementation of Threads in Perl
RFC #47 - Universal Asynch I/O (the moby one)
%SIG - perlvar