我認爲你真正開始你的參數列表功能ets_sup:start/1
。您可以通過在ets_sup:start_link/1
之前添加io:format(...)
來驗證它。
但是執行功能ets_sup:start/1
的過程很早就會因爲shutdown
而很快死亡,而當您的主管與其鏈接時,它也會與其所有子女一起死亡。
您必須從不會死的進程調用此函數(通常,它是應用程序管理器的角色)。例如,做到:
start([A, B]) ->
% spawn a new process
spawn(fun() ->
start_link([A, B]),
% add a loop to keep it alive
loop()
end).
loop() ->
receive
stop -> ok;
_ -> loop()
end.
編輯,但不是一個答案
我已修改了代碼:
- 在init服務器添加
process_flag(trap_exit, true),
,爲了趕退出消息,
- 在服務器終止函數中添加
io:format("server terminate with reason ~p, process ~p~n",[_R,self()]),
以打印最終由主管發送的退出原因(注意:如果a n退出消息由另一個進程發送,handle_info將被觸發)。
- 在監督器中添加
ets_srv:check_sys()
,剛好在服務器啓動之後,以檢查它是否確實正確地顯示了星號。
這裏是修改後的代碼。
-module(ets_sup).
-behaviour(supervisor).
-export([start/1, start_link/1, init/1]).
start([A, B]) ->
start_link([A, B]).
start_link([A, B]) ->
supervisor:start_link({local, ?MODULE}, ?MODULE, [A, B]),
ets_srv:check_sys().
init([A, B]) ->
{ok, {{one_for_all, 0, 1},
[{ets_srv, {ets_srv, start_link, [A, B]}, permanent, 5000, worker, [ets_srv]}]}}.
-module(ets_srv).
-behaviour(gen_server).
-compile(export_all).
-record(state, {a, b}).
start_link(A,B) ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [A, B], []).
init([A, B]) ->
process_flag(trap_exit, true),
{ok, #state{a = A, b = B}}.
check_sys() ->
gen_server:call(?MODULE, check_sys).
handle_call(check_sys, _From, #state{a = A, b = B} = State) ->
io:format("check_sys state ~p, process ~p~n",[State,self()]),
{reply, {A, B}, State}.
handle_info(_Info, State) ->
{noreply, State}.
handle_cast(_Req, State) ->
{noreply, State}.
code_change(_Ol, State, _Ex) ->
{ok, State}.
terminate(_R, _S) ->
io:format("server terminate with reason ~p, process ~p~n",[_R,self()]),
ok.
運行此版本顯示,管理程序正確啓動服務器,然後向其發送關閉消息。如果主管在shell中啓動,則不會發生這種情況。
C:\src>erl -s ets_sup start [email protected] calc
check_sys state {state,'[email protected]',calc}, process <0.56.0>
server terminate with reason shutdown, process <0.56.0>
Eshell V8.2 (abort with ^G)
1> whereis(ets_srv).
undefined
2> ets_sup:start(['[email protected]',calc]).
check_sys state {state,'[email protected]',calc}, process <0.61.0>
{'[email protected]',calc}
3> whereis(ets_srv).
<0.61.0>
4> ets_srv:check_sys().
check_sys state {state,'[email protected]',calc}, process <0.61.0>
{'[email protected]',calc}
5> exit(whereis(ets_srv),shutdown).
true
6> whereis(ets_srv).
<0.61.0>
7> exit(whereis(ets_srv),kill).
** exception exit: shutdown
8> whereis(ets_srv).
undefined
9>
我已經驗證了,如果你使用spawn_link
啓動普通程序(不是管理器)以同樣的方式,它不接受任何退出消息。
-module (st).
-compile([export_all]).
start(Arg) ->
do_start(Arg).
do_start(Arg) ->
io:format("spawn from ~p~n",[self()]),
register(?MODULE,spawn_link(fun() -> init(Arg) end)).
init(Arg) ->
io:format("init with ~p in ~p~n",[Arg,self()]),
process_flag(trap_exit, true),
Pid = self(),
spawn(fun() -> monitor(process,Pid), receive M -> io:format("loop received ~p~n",[M]) end end),
loop(Arg).
loop(Arg) ->
receive
state ->
io:format("state is ~p~n",[Arg]),
loop(Arg);
stop ->
io:format("stopping~n");
_ ->
loop(Arg)
end.
執行給:
C:\src>erl -s st start [email protected] calc
spawn from <0.3.0>
init with ['[email protected]',calc] in <0.55.0>
Eshell V8.2 (abort with ^G)
1> whereis(st).
<0.55.0>
2> exit(whereis(st),shutdown).
true
3> whereis(st).
<0.55.0>
4> st ! state.
state is ['[email protected]',calc]
state
5> st ! stop.
stopping
loop received {'DOWN',#Ref<0.0.4.66>,process,<0.55.0>,normal}
stop
6> whereis(st).
undefined
7>
編輯,另一種方式來「分離」主管
我所做的表明,主管接收到關閉消息的測試。我不知道爲什麼,通常我會使用應用程序機制來啓動一個監督樹,並且我從未遇到過這種情況。
我建議你從其父斷開鏈接的主管,所以不會收到一個關機消息:
-module(ets_sup).
-behaviour(supervisor).
-export([start/1, start_link/1, init/1]).
start([A, B]) ->
start_link([A, B]).
start_link([A, B]) ->
supervisor:start_link({local, ?MODULE}, ?MODULE, [A, B]),
ets_srv:check_sys().
init([A, B]) ->
{links,[Parent]} = process_info(self(),links),
unlink(Parent),
{ok, {{one_for_all, 0, 1},
[{ets_srv, {ets_srv, start_link, [A, B]}, permanent, 5000, worker, [ets_srv]}]}}.
的現在,它的工作原理:
C:\src>erl -s ets_sup start [email protected] calc
check_sys state {state,'[email protected]',calc}, process <0.56.0>
Eshell V8.2 (abort with ^G)
1> ets_srv:check_sys().
check_sys state {state,'[email protected]',calc}, process <0.56.0>
{'[email protected]',calc}
2>