在启动start_child调用的进程中注册子进程

时间:2010-12-03 17:13:12

标签: erlang otp

我有一个逻辑模块,告诉主管启动子进程。我需要将这些儿童的pid存储在逻辑模块状态中。但是如果主管重新启动它,我还需要更新childs pid。

所以我不能使用start_child调用中的返回值pid,因为这只会在第一次启动时给出pid,而不是重启。现在我通过子inits函数在子逻辑模块中调用子进程调用寄存器函数(用新pid更新状态)。这样,只要重新启动进程,逻辑模块就可以在其状态下更新pid。逻辑模块是gen_server,当我注册子进程时,我正在进行强制转换。

任何人都可以看到这个问题,还有其他更“正确”的方法吗?

1 个答案:

答案 0 :(得分:6)

一个问题是你有ChildPid,孩子可能已经死了。因此,通过cast向其发送消息将意味着消息丢失。通过call,您将使用{'EXIT', noproc}使自己崩溃,除非您将其从call中删除。您的解决方案必须考虑到Pid可能会在您发送消息的那一刻消失。通常通过忽略消息丢失,崩溃自己,或通过纠正问题然后继续。

有几种选择。这是一个松散的清单:

  • 照你的意思去做。让孩子自己注册。
  • 让逻辑模块对孩子有一个monitor。那样你知道它是否会死。
  • 使用 Erlang解决方案 gproc 模块:https://github.com/esl/gproc,它为您提供了一个整洁的ETS表接口,可以跟踪信息。请注意,如果进程刚刚重新启动,您可以在gproc中查找pid并等待到达。
  • 使用supervisor:which_children查找相关的孩子。
  • 将您自己的ETS表作为gproc
  • 的变体滚动
  • 本地名称必须是原子,但全局注册的名称可以是任何术语(它们内部存储在ETS表中,看起来有点像gproc,请参阅kernel/stdlib中的> global_name_server 。使用全局结构来跟踪有问题的pids。