如何使支架免受异步异常的影响?

时间:2020-10-21 16:43:50

标签: haskell asynchronous exception concurrency

每一篇有关例外的Haskell文章都重复简单的模式:使用方括号函数分配/释放资源,您将很安全。

我很担心,因为我测试了它的行为并检测到在发布部分中工作时线程可以获取异步异常。

import Control.Exception
import Control.Concurrent

main = do
  tid <- forkIO myThread
  threadDelay 100000
  throwTo tid StackOverflow
  threadDelay 1000000

myThread = 
  bracket 
    (putStrLn "NEW")
    (\() -> threadDelay 500000 >> putStrLn "CLEAN")
    (\() -> putStrLn "USE")

由于异步异常,“ CLEAN”上方的代码段未打印-因此资源泄漏!如何声称它是安全的?

我不知道这一定是原因。 为了确保安全,我需要将每次清洁都包裹在口罩内。看起来笨拙。

1 个答案:

答案 0 :(得分:4)

为确保安全,我需要将每次清洁都包裹在口罩内。

不幸的是,我认为答案就是这样。如果您有为确保资源安全而必须运行 的清理操作,要保持异步异常的资源安全,则必须使用清理过程中不间断的面具。

这类似于将自己限制为Unix / Linux信号处理程序内的信号安全函数或C ++析构函数中的异常安全函数,但此处的条件是“不间断”,无论是调用的函数固有的还是屏蔽的(也许更容易解决问题。

或者,您可以使用unliftio软件包中的bracket,该软件包在其清理处理程序中使用了不间断的掩码。 (与您的问题无关,此程序包提供了MonadUnliftIO类,用于通过无状态包装程序提升IO操作;它是monad-control中较复杂的MonadBaseControl的一种受限替代方法,它处理有状态的包装器覆盖任何基本monad。)