What happens when an Async value is garbage-collected?

concurrency, garbage-collection, haskell, multithreading

Solution

Internally, an `Async` is just a Haskell thread that writes to an STM `TMVar` when finished. A `cancel` is just sending the Haskell thread a kill signal. In Haskell, you don't need to explcititly kill threads. If the `Async` itself can be garbage collected, then the thread will still run to its end, and then everything will be properly cleaned up. However, if the `Async` ends in an exception, then `wait` will propagate the exception to the waiting thread. If you don't `wait`, you'll never know that the exception happened.

Problem

Well... – apparently, nothing! If I try Prelude Control.Concurrent.Async Data.List> do {_ <- async $ return $! foldl'(+) 0 [0,0.1 .. 1e+8 :: Double]; print "Async is lost!"} "Async is lost!" one processor core starts going wild for a while, the interface stays as normal. Evidently the thread is started and simply runs as long as there is something to do. But (efficiency aside), is that in principle ok, or must `Async`s always be either `cancel`led or `wait`ed for? Does something break because there just isn't a way to read the result anymore? And does the GC properly clean up everything? Will perhaps the thread in fact be stopped, and that just doesn't happen yet when I try it (for lack of memory pressure)? Does the thread even properly "end" at all, simply when the `forkIO`ed action comes to an end? I'm quite uncertain about this concurrency stuff. Perhaps I'm still thinking too much in a C++ way about this. RAII / deterministic garbage collection certainly make you feel a bit better cared for in such regards...

Original source