Erlang的supervisor

萬事皆有因

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

相關文章
相關標籤/搜索