[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