core.async 0.5.527 is now available.
In general, you should never directly or indirectly use blocking IO operations in go block threads. The go block threads are a fixed pool of (by default 8) threads. If you block enough of these threads, you lock up the pool, potentially in unrecoverable ways.
This release contains a new Java system property (intended primarily for development use) that will throw if core.async blocking operations (anything ending in "!!") are used in a go block. The exception will be thrown in a go block thread which by default will bubble up to the ThreadGroup's uncaught exception handler and get printed to stderr. You can also set Thread.setDefaultUncaughtExceptionHandler() if you want to do something else. Note that this only catches one set of blocking calls, other blocking IO is equally as problematic and will not be caught with this flag.
Example:
clj -J-Dclojure.core.async.go-checking=true
user=> (require '[clojure.core.async :as a])
nil
user=> (def c (a/chan 10))
#'user/c
user=> (a/go (a/>!! c 100))
#object[clojure.core.async.impl.channels.ManyToManyChannel 0x77a14911 "clojure.core.async.impl.channels.ManyToManyChannel@77a14911"]
user=> Exception in thread "async-dispatch-1" java.lang.IllegalStateException: Invalid blocking call in dispatch thread
at clojure.core.async.impl.dispatch$check_blocking_in_dispatch.invokeStatic(dispatch.clj:29)
at clojure.core.async.impl.dispatch$check_blocking_in_dispatch.invoke(dispatch.clj:26)
at clojure.core.async$fn__6568.invokeStatic(async.clj:164)
at clojure.core.async$fn__6568.invoke(async.clj:164)
at user$eval9097$fn__9098$state_machine__6417__auto____9099$fn__9101.invoke(NO_SOURCE_FILE:1)
at user$eval9097$fn__9098$state_machine__6417__auto____9099.invoke(NO_SOURCE_FILE:1)
....
When running source from a file, the NO_SOURCE_FILE lines will point to the offending file and line performing the blocking operation (here those on the REPL).
Additionally, the `pipeline` api call has been modified, both to respect the policy above and to address issues with reusing the go block thread pool for pipeline concurrency (capped by go block thread pool size).
The api docs have been regenerated: