[erlang] 什么是supervisor_bridge

在OTP的源代码中,我发现了一个陌生的behaviour,名为supervisor_bridge。它的作用是什么,和普通的supervisor又有什么区别呢?

于是我找到了supervisor_bridge.erl这个文件。

首先它是一个gen_server.

-module(supervisor_bridge).
-behaviour(gen_server).
-include("logger.hrl").
%% External exports
-export([start_link/2, start_link/3]).
%% Internal exports
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]).
-export([code_change/3]).

这个behaviour只有两个回调,描述其如何启动,如何终止。

-callback init(Args :: term()) ->
 {ok, Pid :: pid(), State :: term()} | ignore | {error, Error :: term()}.
-callback terminate(Reason :: (shutdown | term()), State :: term()) ->
 Ignored :: term().

发现了这样一段注释,大意是这个模块的功能是当其作为supervisor时,启动和终止子进程都是调用特定的模块中自定义的函数,而不是系统默认的。

%%% This module is built to function as process code
%%% for a process sitting inbetween a real supervisor
%%% and a not start&recovery complient server/system
%%% The process inbetween simulates start&recovery
%%% behaviour of the server/system below.

启动时,会调用特定模块中的启动函数,并link到对应的进程。

init([Mod, StartArgs, Name0]) -> 
 process_flag(trap_exit, true),
 Name = supname(Name0, Mod),
 case Mod:init(StartArgs) of
 {ok, Pid, ChildState} when is_pid(Pid) ->
 link(Pid),
 report_progress(Pid, Mod, StartArgs, Name),
 {ok, #state{mod = Mod, pid = Pid,
 child_state = ChildState, name = Name}};
 ignore ->
 ignore;
 {error, Reason} ->
 {stop, Reason}
 end.
supname(self, Mod) -> {self(),Mod};
supname(N, _) -> N.

子进程退出后,并不会重启,而是直接退出。

handle_info({'EXIT', Pid, Reason}, State) when State#state.pid =:= Pid ->
 case Reason of
 normal ->
 ok;
 shutdown ->
 ok;
 {shutdown, _Term} ->
 ok;
 _ ->
 report_error(child_terminated, Reason, State)
 end,
 {stop, Reason, State#state{pid = undefined}};

主动终结,调用对应模块中的终结函数来结束子进程。

terminate(_Reason, #state{pid = undefined}) ->
 ok;
terminate(Reason, State) ->
 terminate_pid(Reason, State).
 
...
%% This function is supposed to terminate the 'real' server.
terminate_pid(Reason, #state{mod = Mod, child_state = ChildState}) ->
 Mod:terminate(Reason, ChildState).

当使用supervisor_bridge的时候,对应的子进程是否真的启动或者终结了,还是在进行一些别的操作,都可以根据需求自定义。在外界看来,它们的行为和普通的supervisor、worker无异。

作者:Ljzn原文地址:https://segmentfault.com/a/1190000015801529

%s 个评论

要回复文章请先登录注册