[Openmcl-devel] interruptions

Pascal J. Bourguignon pjb at informatimago.com
Fri Feb 24 07:58:20 PST 2012


Gary Byers <gb at clozure.com> writes:

> Sorry to have missed this message.
>
> If you're asking how to affect what happens when the OS-level process
> receives a SIGINT (as would be produced by a user typing ^C), there's
> basically a two-part answer.
>
> The first part is that hooking into what currently happens - where some
> thread, typically the listener, gets forced via PROCESS-INTERRUPT to
> enter a break loop - is awkward.
>
> The second part of the answer is that WAIT-FOR-SIGNAL can be used
> to determine if and when an asynchronous signal like ^C occurs; what
> to do in response is up to you.
> […]


Happily, in my current application, I have a tight inner loop in which I
can call wait-for-signal, and signal a condition when a SIGINT is
detected:

    (define-condition user-interrupt (condition)
      ((signal :initarg :signal
               :initform 0
               :reader user-interrupt-signal))
      (:report (lambda (condition stream)
                 (format stream "~S signal ~D"
                         'user-interrupt
                         (user-interrupt-signal condition)))))


    (defun yield-signals (signals)
      #+ccl
      (dolist (signum signals)
        (when (ccl:wait-for-signal signum 0)
          (signal 'user-interrupt :signal signum))))

In the case of clisp, I guess that being initially a unthreaded
implementation, they have it easier to convert unix signals into lisp
condition, which they do in the case of SIGINT (clisp signals a
SYSTEM:USER-INTERRUPT condition).

ECL has something similar, with its ext::unix-signal-received condition,
sent when a unix signal is received (this is activated with a call to
(ext:catch-signal signum t)).

In all cases, this allows the program to deal with SIGINT, in a lispy
way, using HANDLER-CASE or HANDLER-BIND.






Now in the case of ccl, and for the first part above, I don't see a
published API to deal with it.  As you said, one would have to "hook
into", looking at the implementation.  I can understand that in presence
of multiple threads, signal handling doesn't necessarily "break" running
threads with a lisp condition, but run in some specific thread.  But the
program should be able to provide a function that will do what it has to
do for the given application, eg. call PROCESS-INTERRUPT on the relevant
threads of the application.


So, I guess what I'm asking for here, would be an API to install such a
signal handler, something like:

    (ccl:set-signal-handler signum thunk)

The thunk would be run in whatever thread is processing the unix signal
signum.  NIL could be given to remove it.


One could write:

    (ccl:set-signal-handler +sigint+
       (lambda () 
         (ccl:process-interrupt *application-process*
                                (lambda () (signal 'user-interrupt)))))


and in *application-process*:

    (handler-case
         (progn
           (do-something-lengthy)
           (print 'done))
      (user-interrupt ()
         (print 'interrupted))
      (error (err)
         (print 'error
         (princ err))))



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
A bad day in () is better than a good day in {}.




More information about the Openmcl-devel mailing list