to be clear, in my second example you see the error from the future without using deref
good luck finding your solution On Sat, Jan 2, 2021 at 12:50 PM Austin Haas <aus...@pettomato.com> wrote: > Thank you very much for the explanation, Justin. > > I don't see how I can use futures, though, without blocking on the main > thread (to get the exception when it occurs). I'm spawning a long-running > process that never returns a value. > On Saturday, January 2, 2021 at 12:43:14 AM UTC-8 noise...@gmail.com > wrote: > >> By the time the exception is caught, you are already outside the context >> of the Thread which the repl client is interacting with. The default >> exception handler has no information tying the executing thread to the repl >> process (not to mention the dynamic variables clojure is using to associate >> output from code your client runs with that socket connection). >> >> You probably don't want to rebind the root exception handler to show >> *all* exceptions to your client socket. Which means that you need to set up >> some soft of infrastructure connecting the information about the failed >> function to the socket you are listening to. >> >> I find "future" very convenient for this, it uses a pool which will >> perform better than creating Threads ad-hoc, and will capture Exceptions >> and re-throw when you deref (of course, it's up to you to ensure you deref, >> or use try/catch and otherwise forward the failure information via the >> catch block). Also, it conveys dynamic bindings for things like >> clojure.core/*out* and clojure.core/*err* that java classes don't know >> about. >> >> (ins)user=> (def fut (future (throw (Exception. "oops")))) >> #'user/fut >> (ins)user=> @fut ; waits until deref to raise the error >> Execution error at user/fn (REPL:11). >> oops >> (ins)user=> (def fut2 (future (try (throw (Exception. "oops")) (catch >> Exception e (println "wat\n" e))))) ; prints instead of raising >> #'user/fut2 >> user=> wat >> #error { >> :cause oops >> :via >> [{:type java.lang.Exception >> :message oops >> :at [user$fn__165 invokeStatic NO_SOURCE_FILE 13]}] >> :trace >> [[user$fn__165 invokeStatic NO_SOURCE_FILE 13] >> [user$fn__165 invoke NO_SOURCE_FILE 13] >> [clojure.core$binding_conveyor_fn$fn__5754 invoke core.clj 2030] >> [clojure.lang.AFn call AFn.java 18] >> [java.util.concurrent.FutureTask run FutureTask.java 264] >> [java.util.concurrent.ThreadPoolExecutor runWorker >> ThreadPoolExecutor.java 1128] >> [java.util.concurrent.ThreadPoolExecutor$Worker run >> ThreadPoolExecutor.java 628] >> [java.lang.Thread run Thread.java 834]]} >> >> >> >> On Thu, Dec 31, 2020 at 1:48 PM Austin Haas <aus...@pettomato.com> wrote: >> >>> >>> Problem: When I connect to a socket server and create a thread, >>> exceptions in the thread are printed in the server's process, not the >>> client's. I'd like them to appear in the client's process, where the thread >>> was created. >>> >>> (I'm using the term "process" very generally here, because I don't >>> understand what is going on.) >>> >>> From searching, I understand that there are some other things at play, >>> like System/err, but I don't understand what is happening or how I can work >>> around it. Why does an exception thrown in the client process show in the >>> client process, but an exception thrown in a thread created by the client >>> process shows in the server process? Why doesn't binding *err* in a thread >>> seem to have any effect? Any suggestions or workarounds? >>> >>> I'm not using futures, because this is a long-running process that never >>> returns a value. >>> >>> Example transcript: >>> >>> # Socker server >>> >>> (The only command entered is the first one, which begins with clj. >>> Everything after "user=>" is due to the client below.) >>> >>> $ clj -J-Dclojure.server.myrepl='{:port >>> 5555,:accept,clojure.core.server/repl}' >>> Clojure 1.10.1 >>> user=> My second message. >>> Exception in thread "Thread-0" clojure.lang.ExceptionInfo: My second >>> exception {} >>> at user$eval5$fn__141.invoke(NO_SOURCE_FILE:7) >>> at clojure.lang.AFn.run(AFn.java:22) >>> at java.lang.Thread.run(Thread.java:745) >>> Exception in thread "Thread-1" clojure.lang.ExceptionInfo: My third >>> exception {} >>> at user$eval144$fn__145.invoke(NO_SOURCE_FILE:16) >>> at clojure.lang.AFn.run(AFn.java:22) >>> at java.lang.Thread.run(Thread.java:745) >>> >>> # Client >>> >>> $ nc localhost 5555 >>> user=> (println "My first message.") >>> My first message. >>> nil >>> user=> (throw (ex-info "My first exception." {})) >>> Execution error (ExceptionInfo) at user/eval3 (REPL:2). >>> My first exception. >>> user=> (.start >>> (Thread. >>> (fn [] >>> (println "My second message.") >>> (throw (ex-info "My second exception" {}))))) >>> nil >>> user=> (.start >>> (Thread. >>> (let [out *out* >>> err *err*] >>> (fn [] >>> (binding [*out* out >>> *err* err] >>> (println "My third message.") >>> (throw (ex-info "My third exception" {}))))))) >>> nil >>> My third message. >>> >>> Any clues would be appreciated. Thanks! >>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Clojure" group. >>> To post to this group, send email to clo...@googlegroups.com >>> Note that posts from new members are moderated - please be patient with >>> your first post. >>> To unsubscribe from this group, send email to >>> clojure+u...@googlegroups.com >>> For more options, visit this group at >>> http://groups.google.com/group/clojure?hl=en >>> --- >>> You received this message because you are subscribed to the Google >>> Groups "Clojure" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to clojure+u...@googlegroups.com. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/clojure/d084b0c0-0a1b-4db2-95a1-f38ff894bfa6n%40googlegroups.com >>> <https://groups.google.com/d/msgid/clojure/d084b0c0-0a1b-4db2-95a1-f38ff894bfa6n%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/clojure/8dd61a48-0195-4b2d-bbee-7d24f976268fn%40googlegroups.com > <https://groups.google.com/d/msgid/clojure/8dd61a48-0195-4b2d-bbee-7d24f976268fn%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/clojure/CAGokn9LTHt5-Gpym28HMXP1tbhiHc8p5DRGJR_Q0VQG_Jhf-eA%40mail.gmail.com.