首页 > 代码库 > OTP的supervisor tree如何保证子进程一定随父进程的退出而退出
OTP的supervisor tree如何保证子进程一定随父进程的退出而退出
利用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能够保证子进程总随父进程的退出而退出。
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。