Haskell async and cancel


I was asked to help debug the following code. It’s a simple example meant to be added to a bigger system. There are multiple asynchronous bits of code that update a value, but only one should be completed, furthermore a user event can override the other events. I was not clear on all the details, but the code I was given looked like this.

The output looks like this.

$> stack runghc Main.hs
Main.hs: thread killed

The mixed output from multiple threads is normal, but I was not expecting Main.hs: thread killed. After trying out various functions from the async library, I was able to make it run with _ <- waitAnyCatchCancel [continuous, userEvent]. This cancels the other operations, but it also catches any errors.

We did not realize that cancel works by throwing an error. That is what caused the first version to crash. The Hackage documentation states it clearly:

Cancel an asynchronous action by throwing the ThreadKilled exception to it, and 
waiting for the Async thread to quit.