Two processes can be linked to each other. A link between two
processes Pid1 and Pid2 is created by Pid1 calling the BIF
link(Pid2)(or vice versa). There also exists a number a spawn_link
BIFs, which spawns and links to a process in one operation.

Links are bidirectional and there can only be one link between two
processes.Repeated calls to link(Pid) have no effect.

A link can be removed bycalling the BIF unlink(Pid).


发送Exit Signal

When a process terminates, it will terminate with an exit reason as
explained in Process Termination above. This exit reason is emitted in
an exit signal to all linked processes.

A process can also call the function exit(Pid,Reason). This will
result in an exit signal with exit reason Reason being emitted to Pid,
but does not affect the calling process.

Exit Signal的默认处理方式

The default behaviour when a process receives an exit signal with an
exit reason other than normal, is to terminate and in turn emit exit
signals with the same exit reason to its linked processes. An exit
signal with reason normal is ignored

将Exit Signal转换为普通的进程消息

A process can be set to trap exit signals by calling:

process_flag(trap_exit, true)

When a process is trapping exits, it will not terminate when an exit
signal is received. Instead, the signal is transformed into a
message{'EXIT',FromPid,Reason} which is put into the mailbox of the
process just like a regular message.

An exception to the above is if the exit reason is kill, that is if
exit(Pid,kill) has been called. This will unconditionally terminate
the process, regardless of if it is trapping exit signals or not.



Erlang has a built-in feature for error handling between processes.
Terminating processes will emit exit signals to all linked processes,
which may terminate as well or handle the exit in some way. This
feature can be used to build hierarchical program structures where
some processes are supervising other processes, for example restarting
them if they terminate abnormally.

Refer to OTP Design Principles for more information about OTP
supervision trees, which uses this feature.



  • a进程正常退出 -> b进程正常运行
  • a进程异常退出 -> b进程退出
  • a进程正常退出, b进程中调用了process_flag(trap_exit, true) -> b进程不会收到exit msg,退出
  • a进程异常退出, b进程中调用了process_flag(trap_exit, true) -> b进程不会收到exit msg,退出
  • b进程正常退出 -> a进程正常运行
  • b进程异常退出 -> a进程退出
  • b进程正常退出, a进程中调用了process_flag(trap_exit, true) -> a进程收到{'EXIT',Pid_b,normal}
  • b进程异常退出, a进程中调用了process_flag(trap_exit, true) -> a进程收到{'EXIT',Pid_b,Reason}

看起来第3项和第4项不太正常,似乎跟刚刚介绍的erlang link机制冲突了。出现这种现象的原因,是gen_server不是普通进程,它在一个普通的进程上,添加一些默认的行为,具体到这个问题,就是gen_server在收到来自父进程(>调用start_link>的进程)的{'EXIT',Pid_Parent,Reason}

decode_msg(Msg, Parent, Name, State, Mod, Time, Debug, Hib) ->

case Msg of

{system, From, get_state} ->

sys:handle_system_msg(get_state, From, Parent, ?MODULE, Debug,

{State, [Name, State, Mod, Time]}, Hib);

{system, From, {replace_state, StateFun}} ->

NState = try StateFun(State) catch _:_ -> State end,

sys:handle_system_msg(replace_state, From, Parent, ?MODULE, Debug,

{NState, [Name, NState, Mod, Time]}, Hib);

{system, From, Req} ->

sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug,

[Name, State, Mod, Time], Hib);

{'EXIT', Parent, Reason} ->

terminate(Reason, Name, Msg, Mod, State, Debug);

_Msg when Debug =:= [] ->

handle_msg(Msg, Parent, Name, State, Mod);

_Msg ->

Debug1 = sys:handle_debug(Debug, fun print_event/3,

Name, {in, Msg}),

handle_msg(Msg, Parent, Name, State, Mod, Debug1)