[% setvar title Safe Signals %]

This file is part of the Perl 6 Archive

Note: these documents may be out of date. Do not use as reference!

To see what is currently happening visit http://www.perl6.org/

TITLE

Safe Signals

VERSION

  Maintainer: Uri Guttman <uri@sysarch.com>
  Date: 7 Aug 2000
  Mailing List: perl6-language-flow@perl.org
  Number: 60
  Version: 1
  Status: Developing

ABSTRACT

This RFC describes how Perl6 can support safe signals with multiple techniques.

DESCRIPTION

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.

IMPLEMENTATION

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.

In-line Code

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.

Mailboxes

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

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

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.

Callbacks

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.

Timeouts

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.

use signal pragma

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!!" }

IMPACT

People will stop bitching about perl not having safe signals.

UNKNOWNS

REFERENCES

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