a.erl
-behaviour(supervisor)
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init(Args) ->
{ok, {one_for_one, 10,10},[{b, {b, start_link, Args}, permanent, 5000, worker, [b]}]}.
b.erl
-behaviour(gen_server)
start_link(Args) ->
gen_server:start_link(?MODULE, Args, []).
init(Args) ->
supervisor:start_child(a, {c, {c, start_link, []}, permanent, 5000, worker, [c]}),
{ok, #{}}.
c.erl
-behaivour(gen_server)
start_link(Args) ->
gen_server:start_link(?MODULE, Args, []).
init(Args) ->
{ok,#{}}.
启动supervisor a时,a会启动b,然后b在init里面调用supervisor:start_child,因为start_link在init返回后并且所有子进程创建结束后才会返回,当a调用start_link时,a阻塞,此时b调用start_link后也阻塞了(因为init因为a在阻塞,所以没返回),就形成了死锁。
解决方法就是修改b的代码
b.erl
-behaviour(gen_server)
start_link(Args) ->
gen_server:start_link(?MODULE, Args, []).
init(Args) ->
%% supervisor:start_child(a, {c, {c, start_link, []}, permanent, 5000, worker, [c]}).
a ! start_child,
{ok, #{}}.
handle_info(start_child, State) ->
supervisor:start_child(a, {c, {c, start_link, []}, permanent, 5000, worker, [c]}),
{noreply, #{}}.