Fork me on GitHub
#cider
<
2023-05-24
>
stathissideris15:05:08

has anything changed recently in the cider-interrupt function? It used to be pretty effective at stopping stuff in the REPL and now it seems that pressing it makes the prompt appear but doesn’t stop whatever is running

vemv16:05:21

not that I heard of are you familiar with the fact that it first tries to interrupt gracefully (via Thread/interrupt), and then only uses Thread .stop as a last resource. You may need to try twice to force the stop ping.

stathissideris16:05:59

got it, I just have to hit C-c harder then 😄

cider 2
stathissideris16:05:02

thanks for the tip

vemv16:05:23

Let us know if it persists

stathissideris22:06:32

This seems to be persisting, I have this function:

(defn infinite []
  (while true
    (apply * (range 100))))
I run it in the REPL, I see the CPU of the java process going to 100%, I then press C-c C-c, I get back a responsive REPL but CPU stays at 100%.

stathissideris22:06:00

REPL sample session:

;; Connected to nREPL server - 
;; CIDER 1.7.0 (Côte d'Azur), nREPL 1.0.0
;; Clojure 1.12.0-alpha2, Java 20.0.1
;;     Docs: (doc function-name)
;;           (find-doc part-of-name)
;;   Source: (source function-name)
;;  Javadoc: (javadoc java-object-or-class)
;;     Exit: <C-c C-q>
;;  Results: Stored in vars *1, *2, *3, an exception in *e;
;;  Startup: /usr/local/bin/clojure -A:dev -Sdeps '{:deps {nrepl/nrepl {:mvn/version "1.0.0"} cider/cider-nrepl {:mvn/version "0.30.0"}} :aliases {:cider/nrepl {:main-opts ["-m" "nrepl.cmdline" "--middleware" "[cider.nrepl/cider-middleware]"]}}}' -M:cider/nrepl
user> 
zuper.nlp> (infinite)
ERROR:
zuper.nlp> (+ 1 1)
2

stathissideris22:06:28

the ERROR: line appears some time after I press C-c C-c

stathissideris22:06:33

a subsequent call to (infinite) makes java got to 200%, and it stays there even after being interrupted

stathissideris22:06:58

this is on macOS Monterey (12.3.1)

phronmophobic22:06:40

Does the error occur if you manually call M-x cider-interrupt? I ask because C-c C-c isn't bound to cider interrupt for me, but I'm not totally sure if that's because my setup has been customized.

stathissideris22:06:09

I can try, but:

C-c C-c runs the command cider-interrupt (found in cider-repl-mode-map), which
is an interactive byte-compiled Lisp function in 'cider-client.el'.

It is bound to C-c C-c, C-c C-b, <menu-bar> <repl> <Interrupt evaluation>,
<menu-bar> <repl> <Test> <Interrupt running tests>.

(cider-interrupt)

Interrupt any pending evaluations.

phronmophobic22:06:57

Oh, nevermind. C-c C-c is cider interrupt in the repl for me, but not in the clj file.

phronmophobic22:06:07

Does the problem also happen if you don't load any code and just try it from the user namespace?

stathissideris22:06:31

yes, it still happens in a fresh REPL:

user> (while true
        (apply * (range 100)))
ERROR:
user> 

phronmophobic22:06:49

and you have confirmed the issue happens in a "clean" project without any plugins or dependencies?

phronmophobic22:06:18

Basically, just trying to narrow it down to make sure the problem is cider related rather than some other dependency

stathissideris22:06:31

sure, let me give that a try

stathissideris22:06:00

OK, so I’ve renamed my ~/.clojure to something else (because I had a deps.edn in there) and made a new project that has just a deps.edn file in the folder with:

{:deps {org.clojure/clojure {:mvn/version "1.12.0-alpha2"}}}
And I’m still getting the same behaviour

phronmophobic22:06:43

oh, interesting. I'm seeing it now

stathissideris22:06:56

I can start changing the versions of Clojure, CIDER, the JDK etc to see which one is to blame

stathissideris22:06:09

oh can you actually reproduce it?

phronmophobic22:06:46

I think I was seeing it before, but just didn't check the CPU usage.

stathissideris22:06:10

it’s my fans that gave it away, it’s pretty hot over here

phronmophobic22:06:04

My macbook air quietly churns.

stathissideris22:06:52

would you like me to write this up as an issue on github?

phronmophobic22:06:19

I don't work on cider. I was just trying to help debug.

stathissideris22:06:52

oh, many thanks in any case, I’ll report this and send you the link in case you’d like to mention that you’re also experiencing it

stathissideris22:06:03

maybe mentioning your versions would be helpful

phronmophobic22:06:14

I wanted to check if writing some code to the interruption also had the same problem:

(defn start-thread-and-kill []
  (let [t1 (Thread.
            (fn []
              (infinite)))
        t2 (Thread.
            (fn []
              (Thread/sleep 3000)
              (.stop t1)))]
    (.start t1)
    (.start t2)
    (.join t1)))

stathissideris22:06:06

Interestingly, cider-interrupt works for this:

user> (defn infinite []
  (while true
    (prn :foo)
    (Thread/sleep 1000)))
#'user/infinite
user> (infinite)
:foo
:foo
Execution error (InterruptedException) at java.lang.Thread/sleep0 (Thread.java:-2).
sleep interrupted
user>

phronmophobic22:06:50

if you call thread.stop() in Java 20, it looks like it doesn't stop the thread instead just throws UnsupportedOperationException.

stathissideris22:06:41

but this keeps printing!

(defn infinite []
  (while true
    (prn :foo)))

phronmophobic22:06:57

As mentioned earlier, cider-interrupt first calls thread.interrupt() and then waits a bit before calling thread.stop() , so since sleep checks the interrupt flag, then it works.

phronmophobic22:06:18

If you remove the sleep, then there's no longer any code that checks the interrupt flag

stathissideris22:06:20

yeah, that makes sense

phronmophobic22:06:32

This also gracefully stops:

(defn infinite-with-interrupt []
  (while (not (Thread/interrupted))
    (apply * (range 100))))

phronmophobic22:06:17

So it seems like the root "cause" is that thread.stop() no longer actually stops the thread starting in Java 20.

stathissideris23:06:24

Downgrading to openjdk 17 fixes this

phronmophobic23:06:00

👍 , yes, that's good to double check.

stathissideris23:06:03

Not just that, but also essential for me to have a working REPL while the good developers of CIDER work on a more permanent fix, thank you very much for your help with this!

phronmophobic01:06:26

Just skimmed through the ticket and basically, it doesn't seem like there's any way to force another thread to stop if the thread itself doesn't cooperatively check if it should stop itself.

phronmophobic01:06:13

Maybe some answer will present itself via project loom?

stathissideris22:06:32

This seems to be persisting, I have this function:

(defn infinite []
  (while true
    (apply * (range 100))))
I run it in the REPL, I see the CPU of the java process going to 100%, I then press C-c C-c, I get back a responsive REPL but CPU stays at 100%.