cursive-ide / cursive

Cursive: The IDE for beautiful Clojure code
588 stars 7 forks source link

Interrupt evaluation yields `UnsupportedOperationException` #2864

Open onetom opened 10 months ago

onetom commented 10 months ago

Problem

I'm seeing exceptions like this from time to time, when I try to interrupt some evaluation:

ERROR:
java.lang.UnsupportedOperationException
    at java.base/java.lang.Thread.stop(Thread.java:1667)
    at nrepl.middleware.session$interrupt_stop$fn__9394.invoke(session.clj:198)
    at clojure.core$binding_conveyor_fn$fn__5835.invoke(core.clj:2047)
    at clojure.lang.AFn.call(AFn.java:18)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
    at java.base/java.lang.Thread.run(Thread.java:1583)

Then the evaluation just keeps running, BUT I can submit new forms still and I get back their evaluation result, overlapping with the print-out of the previous evaluation.

It's unclear what's causing it. I tried to have a minimal repro, but I could NOT trigger it with such a simple example:

(loop [] (print "•") (flush) (Thread/sleep 500) (recur))
onetom commented 10 months ago

Here is a screenshot of a real world output of a similar loop-recur expression doing some HTTP calls, in case it helps to give some ideas:

Cursive evaluation interruption fail - Screenshot 2023-12-13 at 16 50 10
cursive-ide commented 10 months ago

Looking at the thread dump, it looks like you're trying to interrupt the evaluation. I believe that Thread.stop() has finally been removed from recent JVMs.

onetom commented 10 months ago

Looking at the thread dump, it looks like you're trying to interrupt the evaluation.

Yes, but that's what issue title says, so I'm not sure what do you mean. I'm pressing the Interrupt Current Evaluation icon on the REPL tool window.

onetom commented 10 months ago

Do you mean, it won't be possible to interrupt evaluations anymore, if we are running on more recent JVMs?

onetom commented 10 months ago

This feature DO work most of the time tough, so I'm a very confused.

onetom commented 5 months ago

This Thread.stop() issue with recent JDKs has been discussed in the nREPL project and nREPL 1.2.0-beta1 has a way to address it: https://github.com/nrepl/nrepl/issues/296#issuecomment-2124840163

So I guess before Cursive would adopt that solution, we should participate in that discussion, to make sure it's a good solution.

onetom commented 5 months ago

btw, here is an example session of what would happen, if i eval some infinite sequences and try to interrupt the evaluation

Loading src/repl.clj... done
(range)
Evaluation interrupted.
123
=> 123
(iterate inc 1)
Session idle - no current executions.
123
Evaluation interrupted.
=> 123
(iterate inc 1)
Session idle - no current executions.
(->> (iterate inc 1)
       (take-while (constantly true)))
Evaluation interrupted.
Evaluation interrupted.
[:is-the-repl-alive?]

<...numerous minutes later...>

Exception in thread "clojure-agent-send-off-pool-6" java.lang.OutOfMemoryError: Java heap space
Error printing return value (OutOfMemoryError) at null (REPL:1).
Java heap space
Execution error (OutOfMemoryError) at (REPL:1).
Java heap space
Execution error (OutOfMemoryError) at (REPL:1).
Java heap space
Error updating completions:
Execution error (OutOfMemoryError) at (REPL:1).
Java heap space
Error printing return value (OutOfMemoryError) at null (REPL:1).
Java heap space
cursive-ide commented 5 months ago

Yes, I just saw all that discussion yesterday. I'll comment over there to clarify how this should work in Cursive.