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.

Reply via email to