В этой ситуации обычно вызывается обратный вызов terminate
, а именно потому, что вы перехватили выходы.
Единственное место, где это не так, это если происходит сбой в функции инициализации. В этом случае ответственность лежит на наблюдателе, который в результате обычно прекращает свою деятельность. Затем эта ошибка ползет по дереву супервизора, пока не завершится завершением всего приложения.
Обычно супервизор регистрирует отчет супервизора с контекстом, установленным на start_error
. Это ваш намек на то, что у части дерева контроля есть проблемы, с которыми вы должны справиться. Вы должны проверить это, поскольку у вас может быть неверное предположение о том, где произошла ошибка.
ИЗД. ЗДЕСЬ
Ваша проблема в том, что вы вообще не знаете о SASL. Изучите это. Вот пример того, как его использовать.
Поднятый код из вашего примера:
Во-первых, бахлонга должен был сказать Эрлангу, что у нас есть сервер gen_server.
-module(foo).
-behaviour(gen_server).
-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
Мы взломали запись #state {}, чтобы ее можно было использовать с вашим кодом
-record(state, { name, port, socket_listen }).
Basic start_linkage ...
start_link() ->
gen_server:start_link({local, foo}, ?MODULE, [], []).
Ваша функция инициализации, включая проблему появления.
init([]) ->
Port = 3252,
Name = "foo",
Выше мы взломали немного ради упрощения ...
process_flag(trap_exit, true),
erlang:error(blabla),
Opts = [binary, {reuseaddr, true},
{backlog,5}, {packet, 0}, {active, false}, {nodelay, true}],
case gen_tcp:listen(Port,Opts) of
{ok,Socket_Listen} ->
logger:fmsg("--> [~s,init] Socket_Listen crée = ~p",
[Name,Socket_Listen]),
{ok,handle_accept(#state{socket_listen=Socket_Listen})};
{error, Reason} ->
logger:fmsg("--> [~s,init] Erreur, Raison =~p",
[Name,Reason]), {stop, Reason}
end.
Хаки для отсутствующих функций ....
handle_accept(_) ->
#state{}.
Остальное - только основы ... поэтому я их опускаю.
Теперь для foo_sup
супервайзер для foo
:
-module(foo_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1]).
-define(SERVER, ?MODULE).
Базовая стартовая ссылка ...
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
Basic ChildSpec. Получи ребенка и беги ...
init([]) ->
FooCh = {foo, {foo, start_link, []},
permanent, 2000, worker, [foo]},
{ok, {{one_for_all,0,1}, [FooCh]}}.
Загрузка Erlang с включенным SASL:
jlouis@illithid:~$ erl -boot start_sasl
Erlang R14B02 (erts-5.8.3) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]
=PROGRESS REPORT==== 9-Dec-2010::01:01:51 ===
[..]
Eshell V5.8.3 (abort with ^G)
Давайте попробуем порождать супервизора ...
1> foo_sup:start_link().
И мы получаем это:
=CRASH REPORT==== 9-Dec-2010::01:05:48 ===
crasher:
initial call: foo:init/1
pid: <0.58.0>
registered_name: []
exception exit: {blabla,[{foo,init,1},
{gen_server,init_it,6},
{proc_lib,init_p_do_apply,3}]}
Выше мы видим, что у нас произошел сбой в foo:init/1
из-за исключения blabla
.
in function gen_server:init_it/6
ancestors: [foo_sup,<0.45.0>]
messages: []
links: [<0.57.0>]
dictionary: []
trap_exit: true
status: running
heap_size: 233
stack_size: 24
reductions: 108
neighbours:
И теперь руководитель получает возможность сообщить о проблеме!
=SUPERVISOR REPORT==== 9-Dec-2010::01:05:48 ===
Supervisor: {local,foo_sup}
Context: start_error
Контекст точно , как я сказал, это будет ...
Reason: {blabla,[{foo,init,1},
{gen_server,init_it,6},
{proc_lib,init_p_do_apply,3}]}
И с ожидаемой причиной.
Offender: [{pid,undefined},
{name,foo},
{mfargs,{foo,start_link,[]}},
{restart_type,permanent},
{shutdown,2000},
{child_type,worker}]