为什么“mask_”会抵消“timeout”?

发布于 2024-11-15 05:42:45 字数 708 浏览 0 评论 0原文

我终于能够跟踪一个奇怪的错误,我遇到了(至少对我来说)masktimeout 之间令人惊讶的交互:

import System.Timeout
import Control.Exception

ack :: Int -> Int -> Int
ack m n | m == 0, n >= 0  = n + 1
        | m >  0, n == 0  = ack (m - 1) 1
        | m >  0, n >  0  = ack (m - 1) (ack m (n - 1))

tryack :: Int -> Int -> IO (Maybe Int)
tryack m n = timeout 100000 {- uS -} $ evaluate $ ack m n

main :: IO ()
main = do
  a <- tryack 3 11
  print a -- Nothing

  b <- mask_ $ tryack 3 11
  print b -- Just 16381 after a few seconds

这让我觉得这是一个相当“非-组合”交互,因为这意味着如果库内部使用超时,则调用链上某处外部应用的掩码可能会导致库发生故障。

那么这是超时实现中的(已知)缺陷还是故意的?

I finally was able to track a weird bug I was having down to the (at least to me) surprising interaction between mask and timeout:

import System.Timeout
import Control.Exception

ack :: Int -> Int -> Int
ack m n | m == 0, n >= 0  = n + 1
        | m >  0, n == 0  = ack (m - 1) 1
        | m >  0, n >  0  = ack (m - 1) (ack m (n - 1))

tryack :: Int -> Int -> IO (Maybe Int)
tryack m n = timeout 100000 {- uS -} $ evaluate $ ack m n

main :: IO ()
main = do
  a <- tryack 3 11
  print a -- Nothing

  b <- mask_ $ tryack 3 11
  print b -- Just 16381 after a few seconds

This strikes me as a rather "non-compositional" interaction, as it means that if a library internally uses timeout, an externally applied mask somewhere up the call-chain may cause the library to malfunction.

So is this a (known) deficiency in the implementation of timeout or is it intentional?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

滥情稳全场 2024-11-22 05:42:45

mask_ 做什么?

执行 IO 计算并屏蔽异步异常。也就是说,任何试图在当前线程中使用 Control.Exception.throwTo 引发异常的线程都将被阻塞,直到异步异常再次被揭露为止。

超时做什么?

如果在 n 微秒(1/10^6 秒)内没有结果可用,则包装 IO 计算以超时并返回 Nothing。如果在超时到期之前有结果可用,则仅返回 a。 ...一个棘手的实现细节是如何中止 IO 计算的问题。该组合器内部依赖于异步异常。

所以... mask_ 正在阻止 timeout 传递异常。就是这样。

您只是不能使用 mask 并让 timeout 起作用。

也许更好的方法是使用处理程序来捕获除 timeout 使用的异常之外的任何内容?

What does mask_ do?

Executes an IO computation with asynchronous exceptions masked. That is, any thread which attempts to raise an exception in the current thread with Control.Exception.throwTo will be blocked until asynchronous exceptions are unmasked again.

And what does timeout do?

Wrap an IO computation to time out and return Nothing in case no result is available within n microseconds (1/10^6 seconds).In case a result is available before the timeout expires, Just a is returned. ... A tricky implementation detail is the question of how to abort an IO computation. This combinator relies on asynchronous exceptions internally.

So... mask_ is preventing timeout from delivering its exceptions. That's just how it is.

You just can't use mask and have timeout work.

Perhaps a better approach would be to use a handler to catch anything but the exception that timeout uses?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文