【问题标题】:How to make bracket safe from async exception?如何使括号免受异步异常的影响?
【发布时间】:2021-02-04 15:17:30
【问题描述】:

每一篇关于异常的 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")

在上面的 sn-p 中,“CLEAN”由于异步异常而没有打印 - 所以资源泄漏!如何声称它是安全的?

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

【问题讨论】:

标签: haskell asynchronous exception concurrency


【解决方案1】:

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

不幸的是,我认为答案正是如此。如果您有必须运行以确保资源安全的清理操作,并且您希望通过异步异常来维护资源安全,那么您必须使用清理期间不间断的掩码。

这类似于将自己限制在 Unix/Linux 信号处理程序中的信号安全函数或 C++ 析构函数中的异常安全函数,除了这里的标准是“不可中断”,无论是您调用的函数固有的,还是通过屏蔽(也许更容易正确)。

或者,您可以使用unliftio 包中的bracket,它在其清理处理程序中使用不间断屏蔽。 (与您的问题无关,此包提供了 MonadUnliftIO 类,用于通过无状态包装器提升 IO 操作;它是来自 monad-control 的更复杂的 MonadBaseControl 的受限替代方案,它处理任何基本 monad 上的有状态包装器。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-14
    • 1970-01-01
    • 2012-04-06
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2014-04-13
    • 1970-01-01
    相关资源
    最近更新 更多