[Openmcl-devel] Unix signal handling

Ron Garret ron at flownet.com
Wed Jul 7 06:39:37 UTC 2010

On Jul 6, 2010, at 11:02 PM, Ron Garret wrote:

> On Jul 6, 2010, at 10:00 PM, Ron Garret wrote:
>> On Jul 6, 2010, at 9:18 PM, Gary Byers wrote:
>>> On Tue, 6 Jul 2010, Ron Garret wrote:
>>>> Actually, on thinking about this some more, a message queue isn't necessary
>>>> because signals are already segregated by the OS.  So something like this
>>>> should work:
>>>> (defmacro set-signal-handler (signo &body body)
>>>> (let ((sem (make-semaphore))
>>>>       (handler (gensym "HANDLER")))
>>>>   `(progn
>>>>      (defcallback ,handler (:int signo :void)
>>>>        (declare (ignore signo))
>>>>        (signal-semaphore ',sem))
>>>>      (#_signal ,signo ,handler)
>>>>      (process-run-function ,(format nil "SIGNAL ~A HANDLER" signo)
>>>>                            (lambda ()
>>>>                              (loop
>>>>                                (wait-on-semaphore ',sem)
>>>>                                , at body))))))
>>>> I tried it and it actually does seem to work.  To really make this
>>>> bulletproof you'd want to tweak it so that calling set-signal-handler
>>>> multiple times on the same signals didn't leave garbage processes lying
>>>> around.
>>>> rg
>>> [I realize that you're just thinking out loud here; sorry if this reply
>>> sounds like an overreaction.]
>>> A few messages ago in this thread, I think that I said something to the
>>> effect that you can't just define signal handlers via the FFI like this:
>>> that it'd work some of the time, but that there were GC issues.  (If
>>> the GC runs in some thread at around the time that the signal handler
>>> runs in another thread, the GC has no way of seeing the state of the
>>> interrupted thread at the time that the signal occurred.)
>>> I did in fact say that, so my conscience is clear in this case.
>> Indeed you did say that.  And I actually read it.  This solution was specifically designed with your caveats in mind.  The signal handler only does one thing: call signal-semaphore, which is itself just an FFI call.  All the Lispy stuff happens in a separate thread.  Is there a reason that would not work reliably?  The kind of GC interaction you describe would seem to me to be impossible if the signal handler thread doesn't cons, and doesn't reference anything that might become garbage.
> Having gone back and re-read your caveats I think I am now very confused.  It seems that having the signal handler not cons and not reference potential garbage has nothing to do with anything.
> But here's what I don't understand in this case: what do signal handlers have to do with anything?  When you're dealing with native threads, can't a thread be interrupted on any instruction boundary whether or not a signal happens?  Isn't that the whole point of native threads, and why they are hard to deal with?
> I seem to be missing something very fundamental here.

Indeed.  I can crash CCL (or at least make it unresponsive) simply by doing simply this:

(defcallback handler (:int signo :void)
  (declare (ignore signo))
  ; Do absolutely nothing

(#_signal #$SIGUSR1 handler)

(process-run-function "foo" (lambda () (loop (setf z (cons t t)))))

and then sending the process a few SIGUSR1s.

So my model of how thread scheduling works must be badly broken.


More information about the Openmcl-devel mailing list