With the beginning
Process.flag(:trap_exit, true) 能够将 Process 发出的 Exit 信号捕获为 Msg,
型号的类型有三类, 分别是 :kill, :normal 和其他
其中被杀的进程本身捕获不到 :kill , 但是其他进程能捕获到, 可以看下面的例子。
:kill
1worker = spawn(fn ->
2 Process.flag(:trap_exit, true)
3
4 receive do
5 msg -> IO.inspect(msg, label: "In worker")
6 Process.sleep(2000)
7 end
8end)
9
10monitor = spawn(fn ->
11 Process.flag(:trap_exit, true)
12 Process.link(worker)
13
14 receive do
15 msg -> IO.inspect(msg, label: "In monitor") # In monitor: {:EXIT, #PID<0.375.0>, :killed}
16 end
17end)
18
19Process.sleep(1000)
20Process.exit(worker, :kill)
21Process.alive?(worker) |> IO.inspect(label: "Worker still alive?") # Worker still alive?: false
:normal
1worker = spawn(fn ->
2 Process.flag(:trap_exit, true)
3
4 receive do
5 msg -> IO.inspect(msg, label: "In worker") # In worker: {:EXIT, #PID<0.297.0>, :normal}
6 Process.sleep(2000)
7 end
8end)
9
10monitor = spawn(fn ->
11 Process.flag(:trap_exit, true)
12 Process.link(worker)
13
14 receive do
15 msg -> IO.inspect(msg, label: "In monitor") # In monitor: {:EXIT, #PID<0.844.0>, :normal}
16 end
17end)
18
19Process.sleep(1000)
20Process.exit(worker, :normal)
21Process.alive?(worker) |> IO.inspect(label: "Worker still alive?") # Worker still alive?: true
如果用别的进程使用 :normal 去杀死一个进程, 那个进程是不会死的, 但是会当场受到 “死讯” , 如上第二段 Code 中, “In monitor” 将会在 worker 打印了死讯后 2 秒后 输出。
如果用别的进程使用 :kill 去杀死一个进程, 那个进程会立即死亡, 连 “死讯” 都不会 收到, 但是和它 link 到一起的其他进程如果 trap_exit , 能收到死掉的进程的死讯。
Result
-
trap exit 时:
-
如果进程以 :normal 为由自杀,它不会死亡,而是收到一条消息 {:EXIT, 自己的 pid, :normal}
-
如果进程以 :normal 为由被他杀,则被杀的进程不会死亡,但会收到一条消息 {:EXIT, 杀手 pid, :normal}
-
如果进程以 :kill 为由被他杀,则会立即死亡,死因是 :kill,没有写遗嘱的机会
-
如果和它 link 到一起的进程死亡,它会收到一条消息 {:EXIT, 死亡进程的 pid, 死亡进程的死因}
-
-
不 trap exit 时:
-
如果进程以 :normal 为由自杀,则它会死,死因是 :normal,但还有写遗嘱的机会
-
如果进程以 :normal 为由被他杀,则什么事都不会发生
-
如果进程以 :kill 为由被他杀,则会立即死亡,死因是 :kill,且没有写遗嘱的机会
-
如果和它 link 到一起的进程死亡,它也跟着一起死,死因和牵连它的进程的死因相同,有写遗嘱的机会
-