[Openmcl-devel] async signals

Gary Byers gb at clozure.com
Fri Sep 16 15:45:09 PDT 2005

On Fri, 16 Sep 2005, [iso-8859-1] Gábor Melis wrote:

> On Thursday 01 September 2005 10:47, Gary Byers wrote:
>> Every time that I've tried to convince myself that unwinding should
>> ignore or defer asynchronous interrupts - and have convinced myself
>> that I understood just when unwinding started, when it ended, and
>> when it was prematurely exited - I convince myself that that's
>> undesirable and less tractable than it'd first seemed.  I'm currently
>> on the latter end of that pendulum, but it was swinging the other
>> way a few weeks ago.
> Heh, that's familiar.
>>> I've read that openmcl checks for pending interrupts at
>>> safe-points.
>> Where, out of curiousity, did you read this ?  (It's not true, but it
>> used to be.  Lisp code can interrupted basically at any time (unless
>> WITHOUT-INTERRUPTS is in effect.)  The "internals" documentation on
>> the website is several years old and is maybe 50% accurate; I think
>> that there's a disclaimer to that effect somewher
> Sorry, I read everything under the sun (or google), but I can't recall
> where it was.
> I have an implementation for sbcl that's mostly working, with the design
> decisions detailed in this mail:
> http://www.caddr.com/macho/archives/sbcl-devel/2005-9/6018.html
> Come to think of it, I should have probably CCed openmcl-devel in that
> mail. It is by no means final, comments are welcome.
> Cheers, Gábor

When I'm on the other end of the pendulum (perhaps that last happened
this morning), I convince myself that there are two mostly disjoint
but equally important concepts (that presumably would lead to an
elegant solution, the details of which are left as an exercise.)

1) When people first started to think about this (in the context of
hardware interrupts), they reached the conclusion that it was
important to assign priorities to interrupts.  To answer the question
"which is more important: finishing closing the file in an
UNWIND-PROTECT cleanup form, or acknowledging the user who's been
pressing ^C for the last minute and is reaching for the power switch
?", you may need to assign arbitrary weights to those events and
use those weights to implement a policy.

I think that commercial MCL had some sort of notion of multiple
interrupt levels at one point in its history; I don't remember if that
was ever implemented in a released version.  My recollection is that
it was abandoned because it was too complicated; I don't remember whether
that meant "too complicated to implement correctly", "too complicated to
use", or both.

In hardware interrupt priority schemes, it's often (usually ? always ?)
the case that RESET has highest priority (it may be unmaskable.)

2) There's an important distinction to be made between code that can't
be safely interrupted (presumably because it's doing some
transaction-like operation and that transaction has to complete
atomically and can't be safely reentered) and code that can't be
safely aborted (can't be interrupted in a way that could cause
a non-local exit to throw past the point of resumption.)  Assuming
that CLOSE is reentrant, it's probably true that it's safe to interrupt
WITH-OPEN-FILE's cleanup form but undesirable to abort past it.  (Unless,
of course, it isn't.)

You can -almost- firewall cleanup forms yourself (ignoring asynchronous
interrupts) via slightly twisted constructs like:

;;; this is WITH-OPEN-FILE's cleanup form, hypothetically.

(let* ((closed nil))
        (close file)
        (setq closed t))
      (go CHECK))
    CHECK (if closed (return))))

but (with good reason) no one would want to write code like that.  It
might be possible to write macros that wrote code like that, and that
might be useful functionality (of possibly limited applicability.)

This sort of firewalling is sometimes useful in the case of callbacks;
it may be hard to know how stateful the foreign code that called you
is, and it may be hard to understand the consequences of throwing/
aborting past that (possibly stateful) foreign code.

I'm not sure that either of these points leads anywhere. I think that
a first reaction that says "the right way for some of these things to
interact is to disable/defer interrupts during cleanup" probably
offers almost as many ways to lose as the status quo and I don't know
that it makes the model simpler.  In most environments, doing
arbitrary things "at interrupt time" is justifiably seen as unwise;
it's not clear that effort expended towards guarding against possibly
unwise actions is well-spent.  (But I confess that I sometimes believe
otherwise ...)

More information about the Openmcl-devel mailing list