我有一个逻辑模块,告诉主管启动子进程。我需要将这些 child 的 pid 存储在逻辑模块状态中。但如果主管重新启动它,我还需要更新子进程的 pid。
所以我不能使用 start_child 调用的返回值 pid,因为这只会在第一次启动时给我 pid,而不是重新启动时的 pid。现在,我让子进程从子进程的 init 函数调用逻辑模块中的寄存器函数(用新的 pid 更新状态)。这样,每当进程重新启动时,逻辑模块就可以更新 pid 的状态。逻辑模块是 gen_server,当我注册子进程时我正在进行强制转换。
有人能看出这个问题吗?还有其他更“正确”的方法吗?
最佳答案
一个问题是您有 ChildPid
并且 child 现在可能已经死了。因此,通过 cast
向其发送消息将意味着消息丢失。通过调用
,您将因{'EXIT', noproc}
而崩溃,除非您从调用
中捕获它。您的解决方案必须考虑到 Pid
可能在您发送消息后就早已消失。通常是忽略消息丢失,让自己崩溃,或者解决问题然后继续。
有几个选项。这是一个松散的列表:
- 照你做的做。让 child 自己登记。
- 让逻辑模块在子模块上有一个
监视器
。这样你就知道它是否死了。 - 使用Erlang解决方案 gproc模块:https://github.com/esl/gproc它为您提供了一个简洁的 ETS 表界面,用于跟踪信息。请注意,如果进程刚刚重新启动,您可以在 gproc 中查找 pid,并等待它的到来。
- 使用
supervisor:which_children
查找相关子项。 - 将您自己的 ETS 表作为
gproc
的变体进行滚动 - 本地名称必须是原子,但全局注册名称可以是任何术语(它们内部存储在 ETS 表中,看起来有点像 gproc,请参阅
kernel/stdlib
中的 >global_name_server)。使用全局结构来跟踪有问题的 pid。
关于erlang - 在启动 start_child 调用的进程中注册子进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4348040/