On Sun, 21 Jan 2001 17:28:49 -0500, Dan Sugalski wrote:

>The issue of 'which thread' comes in with signals. We can tell with real 
>async events, since they'll have thread ownership tags on them if we care, 
>but we can't do that with signals, and then we have the issue of "which 
>thread" to deal with?

Here's how I've dealt with signals in a cooperatively threaded Perl
library.  This design probably is too simple for Perl6, but it might
be useful to consider.


The library maintains threads' parent/child relationships.  Each
thread is something of a session leader for the threads beneath it, at
least where signals are concerned.  Signal events arriving at a thread
are first propagated to its children, and this repeats recursively
down to the leaf nodes on the family tree.  In essence, signal
delivery happens from the leaf threads back up to the ancestors they
were originally destined for.

Operating system signals are posted to the library's "kernel", which
is the ultimate ancestor of every thread.  This effectively (although
perhaps not efficiently) broadcasts OS signals to every thread.

The library's kernel decides which signals are fatal.  It can do this
because it's also the event dispatcher.  Threads that don't handle
fatal signals are stopped.  Each thread has a destructor, so
everything gets a chance to clean up, even after fatal signals.

The library has an extra signal class: nonmaskable.  Every thread that
receives a nonmaskable signal is stopped regardless whether it handled
the signal.  Nonmaskable signals tend to be fictitious.  They are
generated by the library itself, and they're usually meant to signal a
global shutdown.  Two examples:

UIDESTROY is broadcast when a GUI's main window is closed.  The user
wants this program to stop, and so it shall.

ZOMBIE is broadcast when every thread has stopped running, and nothing
is available to restart them.  Imagine two threads playing ping-pong
with an event.  If one drops the ball, both threads' callbacks keep
them alive.  A program can detect when it has no more balls in play
(the queued-event counter is 0) and shut itself down.  (It's a little
more involved than this: Watched filehandles are significant, for
example, so there's a counter for those, too.)


Here are two things Perl6 can do that my library doesn't, but I'm
going to recommend against them in a moment.

Perl6 will know which thread forked which process; it can track
this information to send SIGCH?LD to appropriate threads.

The system's SIGPIPE can be ignored altogether.  Wherever a PerlIO
function returns EPIPE, it can also post SIGPIPE to the same thread.

I haven't implemented thess is my library because they preclude the
ability to set global SIGCHLD or SIGPIPE handlers in some totally
unrelated thread.  Someone out there will want to do this, and it
might just be me.  It helps that these tend to be "survivable"
signals; only the interested threads will ever notice them even when
they're broadcast everywhere.


Apropos of Perl 5: I've experimented long and hard on the language
level in perl 5, and I have a test case for detect them without using
handlers.  It's unreliable though.  That is, it may miss duplicate
signals between checks.  When is this an issue, though?

-- Rocco Caputo / [EMAIL PROTECTED] / poe.perl.org / poe.sourceforge.net


Reply via email to