我正在尝试从受监督的工作进程中终止整个监督树。这是我的监督树:
... // (as in your code: p & end exist already, key & p_ not yet)
auto [key, p_] = load_string(p, end);
p = move(p_);
... // (continue using p)
流程生命周期:
+--------------------------+
| |
+--------+ Sup1: Dynamic Supervisor +---------+
| | | |
| +-------------+------------+ |
| | |
| | |
v v v
+------------------+ +------------------+ +------------------+
| | | | | |
| Job1: Supervisor | | Job2: Supervisor | | Job3: Supervisor |
| | | | | |
+------------------+ +-+-------- +---+--+ +------------------+
| |
| |
| |
| |
v v
+-------------------+ +--------------+
| | | |
| Progress Monitor: | | Work: Worker |
| Worker | | |
| | +--------------+
+-------------------+
:Job
)-> 2名工人DynamicSupervisor.start_child(__MODULE__, spec)
工作者知道给定工作的完成时间one_for_one
工作人员尝试通过调用Progress Monitor
Progress Monitor
有望在DynamicSupervisor.terminate_child(__MODULE__, pid)
回调中执行清理步骤-它正在捕获退出信号问题和发现:
Progress Monitor
是阻塞调用,这意味着它也等待所有子进程也终止,包括调用进程-terminate
DynamicSupervisor.terminate_child
处于死锁状态,无法终止。上级主管发送Progress Monitor
信号,但不会触发Progress Monitor
回调快速解决方法:
从:kill
工作人员异步调用terminate
:
DynamicSupervisor.terminate_child
为Progress Monitor
定义关闭策略:
spawn(fn -> DynamicSupervisor.terminate_child(__MODULE__, pid) end)
它将最多等待5秒钟以等待作业监督树终止,然后将发送Sup1: Dynamic Supervisor
退出信号。这将确保shutdown: 5_000
进程被调用shutdown
回调。
对他们两个都不满意。
问题:
答案 0 :(得分:1)
只需在异步任务Task.async(fn -> Process.exit(Sup1, :shutdown) end)
中调用它,它将终止Sup1,并且所有子项都将关闭
编辑:
如果您需要更漂亮的解决方案,则取决于您需要的东西。在大多数情况下,我创建Bootstrapper worker来执行初始化和其他一些工作。您可以轻松添加其他功能。
因此,考虑以上内容,并且粗略地说,我会在(AppSupervisor
)上方添加另一个DynamicSupervisor,以便它可以启动Bootstrapper并将self()
传递给它(或以本地名称注册)以避免这种注射)。之后,启动时,Bootstrap worker将启动Sup1(您的动态主管)并等待其他消息,例如:terminate_sup1
将关闭Sup1
进程。稍后,在以下某些工作人员中,您可以通过将Sup1
消息投射到引导程序来关闭:terminate_sup1
。还有一扇门,当另一条消息发送给引导程序工作者时,您可以从Sup1重新开始。
此外,如果您只需要关闭Sup1,请使用Task。但是,如果您需要控制,则可以将其置于应该控制它的单个工作进程中,无论它处于启动还是关闭状态。