On Mar 15, 12:24 pm, Raffael Cavallaro <raffaelcavall...@gmail.com> wrote: > <http://groups.google.com/group/clojure/msg/e4f1df8f9f2895be?hl=en> > > shows how to do this > > basically, add the following to your user.clj > > (use 'clojure.contrib.repl-utils) > > (add-break-thread!) > > then whenever you type ctrl-c ctrl-c return, you'll get a break.
I had a number of problems getting this to work in slime, just thought I'd share for anyone else trying it out. First, putting (add-break-thread!) in user.clj adds a break on the main thread, but its the Swank REPL Thread that you actually want to break out of. Calling (add-break-thread!) manually in the *slime-repl clojure* buffer works. Second, you have to switch to the *inferior-lisp* buffer in order for Ctrl-C Ctrl-C to issue the SIGINT which will result in your Swank REPL Thread getting a break. Third, (and most excitingly) doing this will kill the Swank REPL Thread. Calling Thread.stop(Throwable t), which the add-break-thread! machinery does, seems to set the thread's interrupted status (*). Even if you catch the initial SIGINT exception (t), the next call that can throw an InterruptedException (like Object.wait or Thread.sleep) will do so. The process of throwing it clears the interrupted status flag, and after that things are back to normal. Its this InterruptedException which kills the Swank REPL Thread when it occurs unexpectedly. Unfortunately I can't see any way for the add- break-thread!/start-handling-break SIGINT handler to prevent this; I think the thread having .stop called on it has to clean things up itself. I was able to keep the repl thread alive by putting a (Thread/ interrupted) call in swank.core/eval-for-emacs just before the (set! *e t) call. Thread/interrupted clears the current thread's interrupted status. (*) - actually the interrupted status is not set if you are in the middle of a call that can throw InterruptedException, see Thread.interrupt() docs. So for example: user=> (add-break-thread!) {1 #<WeakReference java.lang.ref.weakrefere...@8722c99>} user=> (Thread/sleep 10000) ^Cjava.lang.Exception: SIGINT (NO_SOURCE_FILE:0) user=> (Thread/sleep 10) ; OK, interrupted status has not been set nil user=> (dorun (iterate inc 0)) ^Cjava.lang.RuntimeException: java.lang.Exception: SIGINT (NO_SOURCE_FILE:0) user=> (Thread/sleep 10) ; will throw InterruptedException java.lang.InterruptedException: sleep interrupted (NO_SOURCE_FILE:0) One final note -- start-handling-break resets the break-threads map to {} every time it is called, meaning that add-break-thread! effectively sets the thread its called on as the *only* thread to have a break. Is that a bug? Other than these niggles add-break-thread! gets the job done, and it sure is nice not to have to restart everything. -- Gavin Scott gavindsc...@gmail.com --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---