有没有办法在不重启GHCi会话的情况下杀死所有分叉的线程? [英] Is there a way to kill all forked threads in a GHCi session without restarting it?

查看:130
本文介绍了有没有办法在不重启GHCi会话的情况下杀死所有分叉的线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于我的以前的问题我想问一下在GHCi会话中是否有任何方法可以杀死所有用户创建的线程



原因是当一个函数在GHCi中退出时,它产生的线程不会自动终止,即使通过代码重新加载也会持续存在。重新启动GHCi解决了这个问题,但是由于我的应用程序需要一段时间才能加载,所以如果有可能的(甚至是hacky)解决方法,那将是非常好的。

解决方案 div>

不,实际上几乎与在如果我知道实际的数字,我该如何构建一个ThreadId?:库只是不会给你任何东西来获取 ThreadId s所有(仍在运行)的线程或任何其他工具可用于任何不属于您的线程。



此外,您无法可靠猜测使用 forkIO 产生的线程属于您的GHCi会话(所有评估通常在 forkIO >中进行沙箱化),底层yesod应用程序或线程化的RTS(至少有一次调用 forkIO - 这基本上确保所有事件管理器都关闭)。目前,这并不算太坏,因为GHCi在 main 线程中运行,并且IO管理器无论如何关闭都会重新启动,但在未来的版本中可能会改变。 p>

那么为什么线程甚至会在终止时被收集? hs_exit() 。本质上,它调用 ioManagerDie()(杀死所有活动经理)和 exitScheduler(..)(参见 scheduler ,基本上杀死所有线程。这些函数都没有适当的FFI包装。



时间 hs_exit()被调用,Haskell世界中的 main 已经完成,因为这些函数都没有因为没有合适的:# / code>命令。



因此,总而言之,你不能。在GHCi中,调度器很容易。但是,如果调度程序从 hs_init()开始并停在 hs_exit() https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rtsrel =nofollow noreferrer> RTS模式,我怀疑这是一个简单的扩展。






取决于你想要做什么,你可以作弊。您可以编写自己的 forkIOMem ,它将 ThreadId 存储在全局 MVar ,并替换源文件中的所有 forkIO 。这可能非常麻烦,特别是在使用库时,因为您需要确保 forkIO 在任何地方都被替换为 / em>的。



当然,你可以干预 base 包,但这可能是疯狂的(尽管如此),在> forkIO 那里更改并添加 killAllforkIOs Control.Concurrent (我已经说过这可能是疯狂的,对吧?)


Based on my previous question I'd like to ask if there's any way to kill all user created threads in a GHCi session?

The reason for this is that when a function exits in GHCi the threads that it spawned don't terminate automatically, persisting even through code reloads. Restarting GHCi solves this, but since my application takes a while to load, it would be great if there was a possible (even hacky) workaround.

解决方案

No, and actually for almost the same reasons as in How can I build a ThreadId given that I know the actual number?: The library simply doesn't give you anything to get the ThreadIds of all (still running) threads or any other facility to work on any threads which doesn't belong to you.

Furthermore, you cannot reliably guess which threads spawned with forkIO belong to your GHCi session (all evaluations are usually sandboxed in forkIO), the underlying yesod application, or to the threaded RTS (which has at least one call to forkIO - which basically ensures that all event managers get shut down). Currently, this isn't too bad, since GHCi runs in the main thread and the IO manager gets restarted if shut down anyway, but that could change in future versions.

So why do threads even get collected on termination? hs_exit(). Essentially, it calls ioManagerDie() (killing all event managers) and exitScheduler(..) (see scheduler, which basically kills all threads. None of those functions have an appropriate FFI wrapper.

At the time hs_exit() is called, the main from the Haskell world has already finished. Since none of those functions have an appropriate equivalent in the GHC.* modules, you cannot call them directly in Haskell and therefore in GHCi, since there isn't an appropriate :# command.

So all in all, you can't. If one would add a command to restart the scheduler in GHCi, it would be easy as pie. But given that the scheduler gets started in hs_init() and stopped in hs_exit() in the RTS model, I doubt that this would be a easy extension.


Depending on what you want to do, you can however cheat. You can write your own forkIOMem, which stores the ThreadId in a global MVar, and replace all of forkIO in the sources. That can be very cumbersome, especially if you're working with a library, since you need to ensure that forkIO is replaced everywhere.

You could, of course, meddle with the base package, but that's probably madness (still possible though), change forkIO there and add killAllforkIOs to Control.Concurrent. (I've already said that this is probably madness, right?)

这篇关于有没有办法在不重启GHCi会话的情况下杀死所有分叉的线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆