Re:Why Ruby's Timeout is dangerous (and Thread.raise is terr...
by jwlato on Monday June 03, 2024 @01:11PM
(#40564771)
Absolutely this. And when you look through the bug history of those low-level APIs there's a lot of evidence.
That said, the other big difference with Haskell is the low-level API actually provides functionality to solve the exact problem of an async exception being raised anywhere via `mask`. It's still hard to use correctly but at least it's possible.
Re:Why Ruby's Timeout is dangerous (and Thread.raise is terr...
by valcron1000 on Monday June 03, 2024 @11:20PM
(#40570373)
Async is a bless. So many language that claim to be "great at concurrency" don't even provide 10% of the async API.
There are also plenty of footguns when you attempt to catch exceptions. A piece of code might intend to catch all synchronous exceptions (raised in the current thread) but accidentally catches asynchronous exceptions. Again this is a novice issue. When that happens, cancelling a thread doesn't work because thread cancellation is implemented with async exceptions.
What makes things good is that firstly pure code can only raise exceptions but not catch them. (If you need error handling in pure code, you use the Either monad not exceptions.) This dramatically reduces chances of coding mistakes because exceptions aren't as overused as some other languages. Secondly the Haskell community more or less shuns on direct use of these low-level exception handling APIs and everyone uses the async library https://hackage.haskell.org/package/async-2.2.5/docs/Control... which solves not only this problem but also provides nice abstractions to build concurrent computations. Check out its Concurrently type: you now have an Applicative that represents concurrent computations which reuse all your intuition from all Applicative instances. You don't even need to manually create threads or kill threads. Overall insofar as Haskell being the only language where throwing exceptions at another thread isn't a box of footguns, it's only because the language allows a sufficient amount of abstraction power that frees the programmer from using the error-prone low-level APIs. The actual low-level APIs are still full of footguns.