Zach Kost-Smith | 10 Jun 2012 16:17
Picon

Handling Slime interrupts

Is there a way to handle a Slime initiated user interrupt.

For context: I am writing a shell interaction library and would like to intercept user interrupts in order to call sigstop and, possibly, subsequently call sigcont or sigkill to pause, unpause, or kill the shell process.  From the command line (i.e. without Slime) or the inferior lisp process comint buffer, I can handle the condition sb-sys:interactive-interrupt in SBCL and get results along the lines I would like:

> * (handler-case (loop :while t :do (sleep 1)) (sb-sys:interactive-interrupt (cond) (print "test") (error cond)))
>
> ;; User inputs C-c
>
> "test" ;; <- My code is run
> debugger invoked on a SB-SYS:INTERACTIVE-INTERRUPT in thread #<THREAD
>                                                                "initial thread" RUNNING
>                                                                 {1002940EE1}>:
>   Interactive interrupt at #x7FFFF79CA350.
>
> Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.
>
> restarts (invokable by number or by possibly-abbreviated name):
>   0: [ABORT] Exit debugger, returning to top level.
>
> (#:EVAL-THUNK)
> 0]

However, when the user interrupt initiates from the Slime repl, this handler is bypassed entirely and my wrapper code isn't run.  I don't know enough about the way Slime/Swank uses conditions to understand what is happening here.  Does anybody know how I can successfully handle a user interrupt that is initiated from within Emacs, either via changing my code or hacking on Slime/Swank itself?

Zach KS

<div><p>Is there a way to handle a Slime initiated user interrupt.<br><br>For context: I am writing a shell interaction library and would like to intercept user interrupts in order to call sigstop and, possibly, subsequently call sigcont or sigkill to pause, unpause, or kill the shell process.&nbsp; From the command line (i.e. without Slime) or the inferior lisp process comint buffer, I can handle the condition sb-sys:interactive-interrupt in SBCL and get results along the lines I would like:<br><br>&gt; * (handler-case (loop :while t :do (sleep 1)) (sb-sys:interactive-interrupt (cond) (print "test") (error cond)))<br>&gt; <br>&gt; ;; User inputs C-c<br>&gt; <br>&gt; "test" ;; &lt;- My code is run<br>

&gt; debugger invoked on a SB-SYS:INTERACTIVE-INTERRUPT in thread #&lt;THREAD<br>&gt;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "initial thread" RUNNING<br>&gt;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {1002940EE1}&gt;:<br>

&gt; &nbsp; Interactive interrupt at #x7FFFF79CA350.<br>&gt; <br>&gt; Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.<br>&gt; <br>&gt; restarts (invokable by number or by possibly-abbreviated name):<br>&gt; &nbsp; 0: [ABORT] Exit debugger, returning to top level.<br>

&gt; <br>&gt; (#:EVAL-THUNK)<br>&gt; 0] <br><br>However, when the user interrupt initiates from the Slime repl, this handler is bypassed entirely and my wrapper code isn't run.&nbsp; I don't know enough about the way Slime/Swank uses conditions to understand what is happening here.&nbsp; Does anybody know how I can successfully handle a user interrupt that is initiated from within Emacs, either via changing my code or hacking on Slime/Swank itself?<br><br>Zach KS<br><br></p></div>
Helmut Eller | 10 Jun 2012 22:03

Re: Handling Slime interrupts

* Zach Kost-Smith [2012-06-10 14:17] writes:

> However, when the user interrupt initiates from the Slime repl, this handler
> is bypassed entirely and my wrapper code isn't run.  I don't know enough
> about the way Slime/Swank uses conditions to understand what is happening
> here.  Does anybody know how I can successfully handle a user interrupt that
> is initiated from within Emacs, either via changing my code or hacking on
> Slime/Swank itself?

SLIME uses multiple threads and sb-thread:interrupt-thread to force them
to invoke the debugger.  Presumably SBCL signals
sb-sys:interactive-interrupt only when it receives a SIGINT and only in
the main thread.  Pressing C-c C-c in the non-comint repl sends
something on a socket but no SIGINT.

You could write your own Emacs command 

(defun my-interrupt-command ()
  (interactive)
  (let ((slime-current-thread t))
    (slime-eval 
     `(sb-thread:interrupt-thread 
       (swank::find-worker-thread swank::*emacs-connection* :repl-thread)
       (cl:lambda () (cl:signal 'sb-sys:interactive-interrupt))))))

and bind it to C-c C-c. 

Helmut


Gmane