Welcome! Please see the About page for a little more info on how this works.

0 votes
in REPL by

TLDR: How can I start a "one time use" remote-prepl connection that runs a single command, gets the return value, and then releases all resources used?

I asked this in slack but didn't receive a response. It's probably not usually a big deal in practice but it's been bothering me, so I figured I would more formally log it here.

I was under the impression that short lived remote-prepl clients is an intended usage. That it should enable one to connect to the remote, eval something, get the return value and disconnect.

Some example code I found to this effect is here:

Modified slightly:

(ns prepl-question
  (:require [clojure.core.server :as server])
  (:import [java.io PipedReader PipedWriter]))

(def srv
  (server/start-server {:accept 'clojure.core.server/io-prepl
                        :port   0
                        :name   "srv"}))

(defn remote-eval [code]
  (with-open [reader (PipedReader.)
              writer (PipedWriter.)]
    (.connect reader writer)
    (let [result! (promise)]
          "localhost" (.getLocalPort srv)
          (fn [msg]
            (deliver result! msg)))
        (println "DONE"))
      (.write writer code)
      (.flush writer)

      ;; doesn't print "DONE"
      (let [r @result!]
        (.close reader)
        (.close writer)

        ;;(.write writer ":repl/quit\n") ;; also tried this
        ;;(.flush writer)


(remote-eval "(+ 1 2 3)")

I've found no way to get "DONE" to print, signifying the stopping of the prepl thread loop, with any combination of closing the streams used.

Looking at the remote-prepl source code a bit, it seems like this line here will call close on the reader, but it will be called when the reader is already closed. But at least in the example above, I've found that this causes things to hang forever when close is called the second time. I'm guessing this is related to the issue described here: https://stackoverflow.com/a/45703662, related to the PipedReader/Writer setup.

But I'm not sure if this could be considered a bug in the prepl code or if I'm using it wrong.

1 Answer

0 votes
I tried out the latest patch (with the Printwriter-On changes) as well as the  `(binding [*out* *err*] (flush))` "hack solution" described in that thread. Unfortunately neither worked for me. It's probably related though. I will spend more time with it soon and report back.