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

0 votes
in core.async by

If a go or thread blocks throws an exception, there is nothing in Clojure to catch and handle (or report) the exception. Instead, it propagates up to the ThreadExcecutor which invokes its NO-OP afterExecute() method and is re-thrown, ultimately being displayed on the System.err:

Exception in thread "async-dispatch-32" java.lang.IllegalStateException: Fall down, go boom!

at flashiz.resources.orders$index.invoke(orders.clj:26)
at clojure.lang.Var.invoke(Var.java:411)
at clojure.lang.AFn.applyToHelper(AFn.java:159)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.core$apply.invoke(core.clj:617)
at io.aviso.rook$rook_dispatcher.invoke(rook.clj:225)
at flashiz.async$wrap_sync_handler$fn__9005.invoke(async.clj:34)
at flashiz.resources$authorize_async_rook_middleware$fn__9356$fn__9402$state_machine__3245__auto____9403$fn__9405.invoke(resources.clj:21)
at flashiz.resources$authorize_async_rook_middleware$fn__9356$fn__9402$state_machine__3245__auto____9403.invoke(resources.clj:21)
at clojure.core.async.impl.ioc_macros$run_state_machine.invoke(ioc_macros.clj:945)
at clojure.core.async.impl.ioc_macros$run_state_machine_wrapped.invoke(ioc_macros.clj:949)
at clojure.core.async.impl.ioc_macros$take_BANG_$fn__3261.invoke(ioc_macros.clj:958)
at clojure.core.async.impl.channels.ManyToManyChannel$fn__2256.invoke(channels.clj:80)
at clojure.lang.AFn.run(AFn.java:24)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)


It would be nice if execution of the go/thread block was wrapped in an exception handler that delegated to a default function to report the exception. My goal is to be able to alter that function to report it more nicely and/or write it to a persistent log file.

3 Answers

0 votes

Comment made by: alexmiller

Patches on ASYNC-76 have been applied and exceptions will now flow up to the top of the thread, where they can be caught by the standard Thread uncaught exception handler mechanism or ultimately by the default uncaught exception handler, which can be set for the application. There may still be further changes to support exception handling in thread/go.

0 votes

Comment made by: whilo

I have hit this issue repeatedly as well, so I have implemented a comprehensive error-handling strategy as a library for core.async: https://github.com/replikativ/superv.async

It has certain limitations, e.g. there is no dynamic binding across async boundaries in cljs so the supervisor needs to be carried lexically, and I would prefer a default error-handling concept along the Erlang philosophy to have composable libraries built on core.async. Having said that, it works quite well and should provide you with the necessary means to install a logging supervisor.

0 votes
Reference: https://clojure.atlassian.net/browse/ASYNC-61 (reported by hlewisship)