這件事情的開始是很是加單的,我想把幾個模塊獨立化,變的能夠重複使用。而後就建立了幾個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根本不知道這個變化。監控