这件事情的开始是很是加单的,我想把几个模块独立化,变的能够重复使用。而后就建立了几个application,可是将几个模块整合到同一个项目的时候,犯了一个小小的错误,这个错误虽然不是很致命,可是是一个很是很差的。app
一开始,我有一个主干项目A,建立了SupervisorA。以后我建立了一个项目B,同时建立了一个SupervisorB。而后将两个项目整合的时候,我项目B中的模块X的start_link的代码以下面这样
spa
-module(mod_x). -export([start_link/1]). start_link(opts)-> Child = {mod_y,{mod_y,start_link,[]},permanent,5000,worker,[mod_y], supervisor:start_child(supervisor_b,Child).
而后我在主干项目中的SupervisorA的代码写成了这个样子code
-module(supervisor_a). -export([start_link/0]). -export([init/1]). start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). init([])-> RestartStrategy = {one_for_one, 5, 10}, MFA = {mod_x,start_link,[]}, Child = {mod_x,MFA,permanent,5000,worker,[mod_x]}, {ok, { RestartStrategy,[Child]} }.
此时此刻我想你们已经看出问题了。server
这样执行下来,当打开observer会观察到mod_y的进程是和SupervisorB关联,而不是和SupervisorA关联。我先说下为何是和SupervisorB关联而不是和SupervisorA关联。而后再说下会有什么问题。进程
为何和SupervisorB关联。it
由于supervisor的start_child方法,是经过gen_server:call的方式,让指定的Supervisor经过start_link来建立child。而supervisor的start_link也是让指定的Supervisor经过mod:start_link来建立。换句话,就是supervisor并非使用monitor机制,而是使用trap_exit机制来监控它所建立的进程。io
那么会出现什么问题。class
若是mod_y这个进程,不当心死掉了,那么当咱们经过supervisor:which_children(SupervisorA)去寻找child的pid的时候,咱们是没法拿到正确的Pid。缘由就是上面那个,mod_y死掉后是SupervisorB负责重启的,而SupervisorA根本不知道这个变化。监控