[Openmcl-devel] Unix signal handling

Gary Byers gb at clozure.com
Wed Jul 7 18:27:28 UTC 2010

On Wed, 7 Jul 2010, Daniel Weinreb wrote:

> In this whole discussion, I am wondering whether there
> is some potential confusion due to tacit conflation of
> "Unix asynchronous signals" and "interrupting a
> thread".  The latter could happen due to
> process-interrupt being called, for example.

In CCL, PROCESS-INTERRUPT involves using Unix asynchronous
signals,  but the signal is explicitly sent to a thread
(via #_pthread_kill) rather than to "some thread in the
process" (which is what #_kill does.)

So yes, for a lot of things (SIGINT) the handler gets
called on a more-or-less arbitrary thread; POSIX doesn't
say which thread, and OSes differ in their behavior.  (It's
generally "some thread that doesn't have the signal masked";
it might be "the initial thread".  It's not necessarily "the
thread that the user is pressing ^C to try to interrupt."

> If so, then separating these two subjects might help
> everyone understand better what the issues are.
> For example:
> Gary Byers wrote:
>> CCL's GC moves lisp objects around in memory.  Functions are lisp objects.
>> So: some thread is minding its own business, running the function FOO.
>> A signal is delivered to that thread when the PC is N bytes into FOO.
>> The OS saves the state of the thread (the signal context) and executes
>> the signal handler.  The GC runs and stops all other threads; 
> I have two questions.
> (1) Could the GC be made aware of the signal context involving
> FOO and the signal handler? Very hypothetically: the GC looks
> at the PC of the stack, and sees that it's in between X and Y,
> which means that this thread is handling a Unix async signal.
> Between X and Y there is some convention about how registers
> are used and such so that the GC knows what it needs to know?

The general solution is for the handler to receive the signal
context as an argument and store that context in thread-local
storage (where the GC can find it.)

> (2) Is there some way that running the GC could be deferred
> while the stack is inside the interrupt handler?

The GC doesn't run until all other threads are stopped (by sending
them a "suspend" signal) and have acknowledged the request to
suspend themselves.

Signal handlers are generally entered with all signals (especially
the "suspend" signal) masked/blocked, and they only unmask those
signals when they've made their signal context (potentially) visible
to the GC.
> The answer to the above might depend on whether (a)
> after the async interrupt is delivered, the thread might
> call some Lisp code, a la process-interrupt, versus
> (b) when a Unix async signal arrives, the handler
> just does some simple thing like set a bit in a
> field, and then return; the bit is seen later by
> the housekeeping thread or something.

Yes.  In general, decsisions about what what thread should actually
respond to something like SIGINT are above the pay grade of the
actual handler and it's usually OK to defer those decisions until
later (for some value of "later".)

More information about the Openmcl-devel mailing list