标签:erlang otp supervisor gen_server
利用OTP行为包构建的应用之所以可靠,是因为我们按照OTP的设计模式,将所有进程组织成了一棵可靠的supervisor tree。每一个supervisor监控其子进程,并在其子进程出错时按照重启策略进行相应的处理。
但是,你是否考虑过,如果supervisor意外终止,其子进程会怎样?当然,直觉告诉我们连监控进程的没有了,所有的子进程应全部终止。但是,你在代码中是否真正考虑过这种情况?你的gen_server可否写过如下代码?
handle_info({‘EXIT‘, Parent, Reason}, _) %% Parent is the supervisor of the gen_server
事实上,无论你写不写上述代码,你的gen_server、gen_event和gen_fsm都会随其supervisor的结束而结束,但是这是为什么呢?
让我们来看看gen_server的源代码gen_server.erl:
328 loop(Parent, Name, State, Mod, hibernate, Debug) -> 329 proc_lib:hibernate(?MODULE,wake_hib,[Parent, Name, State, Mod, Debug]); 330 loop(Parent, Name, State, Mod, Time, Debug) -> 331 Msg = receive 332 Input -> 333 Input 334 after Time -> 335 timeout 336 end, 337 decode_msg(Msg, Parent, Name, State, Mod, Time, Debug, false).
loop是gen_server的主循环,gen_server在初始化结束后即会陷入loop循环,接收消息并交由decode_msg/8处理。
下面让我们来看看decode_msg/8的源代码:
346 decode_msg(Msg, Parent, Name, State, Mod, Time, Debug, Hib) ->
347 case Msg of
348 {system, From, Req} ->
349     sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug,
350               [Name, State, Mod, Time], Hib);
351 {‘EXIT‘, Parent, Reason} ->
352     terminate(Reason, Name, Msg, Mod, State, Debug);
353 _Msg when Debug =:= [] ->
354     handle_msg(Msg, Parent, Name, State, Mod);
355 _Msg ->
356     Debug1 = sys:handle_debug(Debug, fun print_event/3,
357                   Name, {in, Msg}),
358     handle_msg(Msg, Parent, Name, State, Mod, Debug1)
359 end.
在第351行我们可以看到,gen_server收到的所有消息在交由我们写的回调函数处理之前,已经在decode_msg/8中做过预处理,而其对{‘EXIT‘, Parent, Reason}的反应便是以相同Reason退出。
在gen_fsm和gen_event中我们也能找到相同的处理,而supervisor本身是gen_server实现的,所以使用OTP定义的四大行为构建的supervisor tree能够保证子进程总随父进程的退出而退出。
OTP的supervisor tree如何保证子进程一定随父进程的退出而退出,布布扣,bubuko.com
OTP的supervisor tree如何保证子进程一定随父进程的退出而退出
标签:erlang otp supervisor gen_server
原文地址:http://blog.csdn.net/taotaotheripper/article/details/25230967