如何处理或避免BlockedIndefinitelyOnSTM异常?

2024-06-18

我花了很多时间来解决我正在处理的应用程序中遇到的问题。该应用程序是一个 Web 应用程序,使用 scotty 公开 REST 端点。它使用一个TVar保持其更新的状态STM a由前端层触发的动作。

由于该应用程序基于事件溯源原则,因此业务层生成的任何事件after完成的 STM 事务存储到EventStore(目前是一个简单的平面文件...)。这是相关的代码片段:

newtype (EventStore m) => WebStateM s m a = WebStateM { runWebM :: ReaderT (TVar s) m a }

  deriving (Functor,Applicative,Monad, MonadIO, MonadTrans, MonadReader (TVar s))


    applyCommand :: (EventStore m, Serializable (Event a)) =>
                    Command a                                    
                 -> TVar s
                 -> WebStateM s m (Event a) 
    applyCommand command = \ v -> do
      (e, etype :: EventType s) <- liftIO $ atomically $ actAndApply v
      storeEvent e etype
      return e
      where
        actAndApply =  \ v -> do
          s <- readTVar v
          let view = getView s
          let e  = view `act` command
          let bv = view `apply` e

          modifyTVar' v (setView bv)

          return (e, getType view)

这工作得很完美,直到一个错误溜进了storeEvent功能。该函数负责使用适当的类型序列化事件,而我在某些类型的序列化例程中犯了一个(严重)错误,导致无限循环!然后突然之间,我的cabal test开始挂起并因超时而失败(我使用 wreq 作为客户端库来测试 REST 服务)。我花了几个小时才确定服务器端的实际错误:tests: thread blocked indefinitely in an STM transaction。由于怀疑序列化例程,我又花了几个小时才确定罪魁祸首并解决问题。

尽管我当然对这个错误负全部责任(我应该更彻底地测试我的序列化例程!),但我发现它相当具有误导性。我想更好地了解这个错误从何而来以及如何防止它。我读过了杨德昌的 http://blog.ezyang.com/2011/07/blockedindefinitelyonmvar/关于该主题的帖子,以及这个邮件线程 http://haskell.1045720.n5.nabble.com/Avoiding-BlockedIndefinitelyOnSTM-exceptions-td5752644.html但我必须承认,导致观察到这个错误的事件的逻辑链对我来说并不完全清楚。

我想我理解线程调用applyCommand,由 scotty 生成,因评估时启动的某些异常(堆栈耗尽?)而死亡storeEvent,但我不明白这与交易有何关系garbage.


例外情况says一个线程尝试进行一笔交易,然后点击retry,当事情发生变化时,它将重新运行事务。但是它正在等待更改的东西不再被任何地方引用,因此重试可以never发生。这是一个错误。基本上该线程现在已挂起。

I would imagine某个地方的某个线程是supposed更新这个TVar,但它因异常而死亡,从而删除了对该对象的最后一个引用TVar并引发异常。

这就是我think发生了。如果没有看到整个应用程序,就很难确定。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何处理或避免BlockedIndefinitelyOnSTM异常? 的相关文章

  • 对参数进行排序以利用柯里化

    我最近两次重构代码以更改参数的顺序 因为代码太多 黑客喜欢flip or x gt foo bar x 42正在发生 在设计函数签名时 哪些原则可以帮助我充分利用柯里化 对于轻松支持柯里化和部分应用的语言 有一系列令人信服的论点 最初来自
  • Winforms 多线程:每次在 UI 线程上调用方法时是否需要创建一个新的委托?

    我想调用一个在 UI 线程上操作控件的方法 我的代码可以运行并且我想优化 我指的是这个MSDN 上的资源 http msdn microsoft com en us library 757y83z4 28VS 71 29 aspx 根据那里
  • 查询Python的threading.Lock是否加锁

    我正在运行一个线程 下面的代码 它启动一个阻塞子进程 为了确保其他线程不会启动相同的子进程 我对此进行了锁定subprocess call称呼 我还希望能够终止这个子进程调用 所以我有一个从其他地方调用的停止函数 如果子进程提前停止 我也想
  • 从 Android 中的 Thread 更新 UI

    我想从更新进度条的线程更新我的用户界面 不幸的是 当从 可运行 更新进度条的可绘制对象时 进度条消失了 更改进度条的可绘制部分onCreate 另一边有效 有什么建议么 public void onCreate Bundle savedIn
  • 为连续可测量的现象创建行为

    我想创建一个Behavior t a从一个IO a 其预期语义是每次行为发生时都会运行 IO 操作sampled language FlexibleContexts import Reflex Dom import Control Mona
  • 从外部函数访问 QLCDNumber 对象

    每次线程 t1 每秒调用函数 wait thread v1 时 我的 python 脚本都需要更改一个对象 lcd p1 但是如何做到这一点呢 我不知道如何在函数内访问这个对象 有人可以帮忙吗 vazao1 12 global pulses
  • OpenCV C++ 多线程

    我在 4 个不同的 Mat 对象上调用了 4x 这个 opencv 图像处理函数 void processBinary Mat binaryMat image processing 我想要对其进行多线程处理 以便所有 4 个方法调用同时完成
  • 记录语法和求和类型

    我有关于 Haskell 中的总和类型的问题 我想创建一个由两个或多个其他类型组成的总和类型 并且每个类型可能包含多个字段 一个简单的例子是这样的 data T3 T1 a Int b Float T2 x Char deriving Sh
  • Node.js 多线程程序

    我编写了一个 node js 脚本来从交易所获取一些价格 它看起来像这样 async function main async function func var start time performance now for let rout
  • C#:监视器 - 等待、脉冲、PulseAll

    我很难理解Wait Pulse PulseAll 他们都能避免僵局吗 如果您解释一下如何使用它们 我将不胜感激 简洁版本 lock obj 是简写Monitor Enter Monitor Exit 异常处理等 如果没有其他人拥有锁 您可以
  • 自动函子实例

    给定以下代数类型 ghci gt data Foo a Foo a 然后我实例化其中之一 ghci gt let f Foo foo 最后 我想打电话给fmap将函数应用为 a gt b gt Foo a gt Foo b ghci gt
  • 关注点分离:什么时候最好将语义与语法分离?

    Choices 类型类的出色之处在于它们允许我们将额外的结构连接到现有类型 从而使我们能够推迟一些设计决策 而不是在构思时匆忙做出决定 另一方面 例如 在面向对象编程中 我们被迫考虑类型需要立即执行什么操作 以及稍后出现的或需要的任何附加结
  • Python 多处理进程在一段时间后休眠

    我有一个脚本 它运行一个目录 并搜索具有给定结尾 即 xml 的所有文件以查找给定字符串并替换它们 为了实现这一点 我使用了 python 多处理库 作为示例 我使用 1100 个 xml 文件 其中包含大约 200MB 的数据 在我的 M
  • java 线程看不到共享布尔值更改

    这是代码 class Aux implements Runnable private Boolean isOn false private String statusMessage private final Object lock pub
  • 在单独的线程中从服务获取 AutoCompleteTextView 建议

    For my AutoCompleteTextView我需要从网络服务获取数据 由于这可能需要一点时间 我不希望 UI 线程没有响应 因此我需要以某种方式在单独的线程中获取数据 例如 从 SQLite DB 获取数据时 使用以下命令非常容易
  • 使用BackgroundWorker更新UI而不冻结...?

    我有以下代码用于从后台线程填充 ListView DoWork 调用 PopulateThread 方法 delegate void PopulateThreadCallBack DoWorkEventArgs e private void
  • 广播接收器和处理程序哪个更有效?

    我知道广播接收器的onReceive 和Handler的handleMessage 运行在同一个UI线程上 假设我想在同一个应用程序 进程 内的两个服务之间进行通信 我可以扩展广播接收器类并注册事件 OR 一个 Handler 然后将其实例
  • Linux 内核 - 如何停止等待信号量的 kthread?

    在编写 Linux 内核模块时 我遇到了一个 kthread 问题 在等待信号量解锁时无法唤醒该 kthread 这会导致线程不可停止并且rmmod尝试卸载模块时冻结 请注意 该模块在 3 10 内核上运行 我无法将其更新到较新的版本 客户
  • 如何防止 Parallel.ForEach 循环在运行时更改任务数量?

    我正在使用Parallel ForEach循环做一些工作 我用localInit像这样 localInit gt new foo new Foo bars CreateBars 根据文档 https learn microsoft com
  • 在多个线程中添加和删除时 List 中的 null 值

    我知道 C System Collections Generic List 对象不是线程安全的 但我想知道为什么这段代码会生成空值 Task Run gt for var i 0 i lt 10 i var str Test i list

随机推荐