Fork me on GitHub
#cursive
<
2021-06-28
>
potetm14:06:52

Are there any plans to get “Interrupt Current Evaluation” working for socket repls?

imre14:06:19

I'm not sure that's possible, I think it's a feature of nrepl

potetm14:06:10

It’s possible. It’s a matter of what payload you use to set things up.

potetm14:06:40

nrepl just wraps every execution on a thread, and it calls Thread/kill on cancelation

potetm14:06:29

At worst cursive would rely on the user to set up a specific :accept fn.

imre14:06:52

I see. I'm probably not well-informed in the topic, I only based my initial comment on what I read in the article I linked

cfleming00:06:22

Cursive could do this, yes, since it implements a simple protocol over a socket REPL. However there are complications with that, as you might expect - each eval is then in a different thread and needs dynamic bindings propagated etc. Currently with socket REPLs the evaluations are strictly sequential, but once evals are in separate threads that’s no longer the case, and there is potential weirdness around that too. In general the idea with the socket REPL was to try to keep things simple, and I’m not sure whether that counts 🙂

potetm00:06:58

Yeah, I prefer the mental model for sure. Unfortunately, a great deal of my work involves starting an infinite loop of some sort, and being unable to run them without restarting a repl really stinks.

cfleming00:06:02

Cursive’s protocol is similar to pREPL, but it’s structured in both directions, not just on returns.

cfleming00:06:10

Yeah, I can see that. I guess one potential middle ground would be to use a single background thread for evals which could be cancelled. That would maintain the sequential nature, but would still require bindings to be maintained etc.

potetm00:06:25

Aren’t bindings mostly out-of-the-box via bound-fn*?

potetm00:06:30

Or am I missing smth?

potetm00:06:42

otoh, now that you say that, I could just take care to always kick those off in a future.

potetm00:06:50

somehow never occurred to me :derp:

cfleming00:06:22

Right, you could always do it manually yourself, which is a bit fiddly but possible.

potetm00:06:36

But I also really like that middle ground that you mention, if you ever get around to it. No complicated session mgmt business. Just a dedicated solo thread pool.

potetm00:06:25

In the meantime I’ll try out being vigilant with my infinite loops. If I fail catastrophically, I’ll be sure to let you know 😉

cfleming00:06:36

But as you can see, there’s really no thread management required at all, which keeps it really nice and simple.

👍 3
cfleming00:06:47

And no fiddly bindings management.

potetm01:06:24

oh I know nrepl

potetm01:06:39

I would never ask you to go there 😄

potetm01:06:11

I was unlucky enough to have a serious run in with piggieback. The beast is real.

cfleming01:06:22

Haha, I have to go there pretty regularly. Anyway, the answer is: it’s possible, but I’m not sure it’s desirable. I’d have to try a PoC and see how it ends up.

cfleming01:06:33

Well, piggieback is a whole extra level of madness.

💯 3
potetm01:06:10

Yeah, well. Consider it un-asked until I get back to you. I don’t think it’s crazy to pre-wrap in a future and self-manage.

potetm01:06:40

I was kind of stuck in the mindset of, “Feature exists here. I want it there.”

cfleming01:06:31

Hehe, totally fair enough. Let me know if manually wrapping either doesn’t work or is unreasonably painful. You could potentially use REPL commands to make it easier.

👍 3
borkdude09:06:44

@U07S8JGF7 afaik, nREPL uses Thread#stop which has long been deprecated

borkdude09:06:49

I have a similar problem with the nREPL server of babashka. I can't use Thread#stop there because it's not supported anymore in the GraalVM JDK

borkdude09:06:31

Someone on the graalvm slack suggested to me to use safepoints

borkdude09:06:40

haven't looked into it though

potetm13:06:53

It does use stop, but I’ve never had a problem with it.

potetm14:06:57

AFAIK the biggest problem with stop is that it doesn’t release monitors — which aren’t really an issue in clojure.

potetm14:06:16

at any rate, an interrupt would probably do

borkdude14:06:52

an interrupt won't kill a thread running (doall (range))

cfleming22:06:33

There’s no way to kill that (or in general, any uncooperative REPL process) except Thread/kill

borkdude22:06:12

you mean Thread#stop right

cfleming22:06:17

Yes, that one.

cfleming22:06:59

BTW the problem is not actually that monitors are not released, it’s quite the opposite: > Stopping a thread causes it to unlock all the monitors that it has locked. (The monitors are unlocked as the ThreadDeath exception propagates up the stack.) If any of the objects previously protected by these monitors were in an inconsistent state, other threads may now view these objects in an inconsistent state. Such objects are said to be damaged. When threads operate on damaged objects, arbitrary behavior can result. This behavior may be subtle and difficult to detect, or it may be pronounced. Unlike other unchecked exceptions, ThreadDeath kills threads silently; thus, the user has no warning that his program may be corrupted. The corruption can manifest itself at any time after the actual damage occurs, even hours or days in the future.

cfleming23:06:40

The risk is pretty low for a REPL IMO

✔️ 5
potetm23:06:48

Ah yeah, that’s right.