Jak*_*old 11 multithreading haskell ghc yesod
基于我之前的问题,我想询问是否有办法在GHCi会话中杀死所有用户创建的线程?
这样做的原因是当一个函数退出GHCi时,它产生的线程不会自动终止,即使通过代码重新加载也会持久化.重新启动GHCi解决了这个问题,但由于我的应用程序需要一段时间才能加载,如果有可能(甚至是hacky)的解决方法,那将会很棒.
不,实际上,出于与我知道实际数量的情况下如何构建ThreadId中所述相同的原因?:该库根本不提供任何东西来获取ThreadId所有(仍在运行中的)线程或任何其他工具来处理不属于您的任何线程。
此外,您无法可靠地猜出产生的线程forkIO属于您的GHCi会话(所有评估通常都在中进行沙盒处理forkIO),底层yesod应用程序或线程RTS(至少具有一个调用forkIO-基本上确保了所有事件管理器)关闭)。目前,这还算不错,因为GHCi在main线程中运行,并且无论如何关闭都会重新启动IO管理器,但是在将来的版本中可能会发生变化。
那么,为什么在终止时甚至会收集线程?hs_exit()。从本质上讲,它调用ioManagerDie()(杀死所有事件管理器)和exitScheduler(..)(请参阅调度程序,它基本上杀死了所有线程。这些功能都没有合适的FFI包装器。
在hs_exit()被称为时间的时候,main来自Haskell的世界已经完成了。由于这些功能在GHC.*模块中都没有适当的等效项,因此,由于没有适当的:#命令,因此无法直接在Haskell中以及GHCi中直接调用它们。
所以总的来说,你不能。如果添加一条命令以重新启动GHCi中的调度程序,那将很容易。但是鉴于调度程序hs_init()是hs_exit()在RTS模型中启动和停止的,所以我怀疑这是否是一个简单的扩展。
但是,根据您想做什么,您可以作弊。您可以编写自己的forkIOMem,将其存储ThreadId在global中MVar,然后替换所有forkIO源中的。这可能非常麻烦,尤其是在使用库的情况下,因为您需要确保在任何地方都将forkIO其替换。
您当然可以混入该base程序包,但这很疯狂(尽管仍然可能),forkIO在那里进行更改并添加killAllforkIOs到中Control.Concurrent。(我已经说过这可能是疯狂的,对吧?)