How to abort a long running operation at the SLIME REPL?

748 views
Skip to first unread message

Tassilo Horn

unread,
Mar 15, 2009, 11:46:41 AM3/15/09
to clo...@googlegroups.com
Hi all,

when experimenting at the SLIME REPL it often happens to me that I eval
an expression which runs very long (or infinitively). This may be
intended, like to prove that (some #(= 12 %) primes) will run forever
(it does).

The question is: How do I abort such an evaluation? Currently I do ",
sayoonara" which quits the whole SLIME process. But then I loose my
whole environment, e.g. the namespaces I used and the variables and
functions I've defined.

So is there a more decent way to quit the current evaluation?

Bye,
Tassilo

Raffael Cavallaro

unread,
Mar 15, 2009, 1:24:17 PM3/15/09
to Clojure
<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.

Tassilo Horn

unread,
Mar 15, 2009, 2:04:23 PM3/15/09
to clo...@googlegroups.com
Raffael Cavallaro <raffaelc...@gmail.com> writes:

Hi Raffael,

> <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!)

Hm, but C-c C-c only issues a SIGINT if `slime-use-sigint-for-interrupt'
returns non-nil, and that's only the case if connection style is
:fd-handler.

Anyway, now it's only a SLIME config issue I'll look up and solve
somehow.

Thanks a lot,
Tassilo

gdscott

unread,
Mar 17, 2009, 11:56:09 PM3/17/09
to Clojure
On Mar 15, 12:24 pm, Raffael Cavallaro <raffaelcavall...@gmail.com>
wrote:
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.WeakReference@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
gavin...@gmail.com


Chouser

unread,
Apr 15, 2009, 11:07:12 AM4/15/09
to Clojure
On Mar 17, 11:56 pm, gdscott <gavindsc...@gmail.com> wrote:
>
> 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?

Yep, thanks for the report.

Fixed in contrib 669

--Chouser

ron

unread,
Mar 16, 2015, 11:54:14 PM3/16/15
to clo...@googlegroups.com, raffaelc...@gmail.com
Hi!..given than clojure contrib is deprecated, which could be the option now?...(thread-stopper or set-break-handler from clojure.repl maybe?) 

2) this could work with a non ring server?..I'm using other server which doesnt provide a function for shutdown nor restart, how could use it for this approach?...

thanks!... 
Reply all
Reply to author
Forward
0 new messages