如何使括号免受异步异常的影响?

Dan*_*kov 8 concurrency haskell asynchronous exception

每一篇关于异常的 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")
Run Code Online (Sandbox Code Playgroud)

在上面的代码段中,由于异步异常,“CLEAN”未打印 - 所以资源泄漏!怎样才能称得上安全?

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

Jon*_*rdy 4

\n

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

\n
\n

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

\n

它\xe2\x80\x99类似于限制自己使用Unix/Linux信号处理程序中的信号安全函数或C++析构函数中的异常安全函数,不同之处在于这里的标准是\xe2\x80\x9cuninterruptible\xe2\x80\x9d,无论是您调用的函数所固有的,或者通过屏蔽(也许更容易正确实现)。

\n

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

\n