本文主要记录各类状况下gen_server进程退出的表现。网络
研究动机起源于Elixir/Phoenix框架中遇到的一个进程异常退出问题。由于网络异常,客户端超过一段时间未发来消息,channel进程(一个gen_server)退出了,可是挂的很突兀,不调用 terminate,进而致使掉线处理没被调用,表现出一堆bug。分析发现它是被shutdown的,而一个gen_server若是没有trap_exit,被shutdown就不会调用terminate。框架
Anyway,实验了各类组合,仅以此作个记录。个中原因有兴趣的能够阅读源码。orm
当trap_exit不为true时,Process.exit(Pid, normal) 只有在自身调用时才会退出,其余进程中调用不会致使退出。而除normal外的其余任何一种Reason都会致使进程退出。server
当trap_exit=true时,全部Reason都会致使进程退出,也就是说其余进程也能用 normal 退出该进程。进程
Reason=kill 时 terminate 回调不会被调用,而Reason为其余值均会调用。源码
Reason 不属于 normal、shutdown、kill时,还会触发gen_server的exit log。it
主动退出是指进程主动在回调中返回 {stop, Reason, State} 的状况。bug
这种状况下,全部Reason都会触发 terminate 回调,而除 normal 和 shutdown 外,其余Reason都会触发gen_server的exit log。channel
当trap_exit不为true时,父进程退出至关于Process.exit(Pid, Reason) 状况。因为不是自身调用,normal不会致使子进程死亡,其余理由均会致使进程死亡,而且不会调用 terminate 回调。客户端
当trap_exit=true时,全部Reason都会致使进程退出,而且全部Reason都会触发 terminate 回调。
除 normal 和 shutdown外,其余Reason均会触发gen_server的exit log。
以上全部的退出方式中,只有退出理由为 normal ,才不会往父进程辐射死亡信号。
而父进程收到死亡信号,若是父进程trap_exit不等于true,则会以同一理由随之死亡并往上传递,如trap_exit=true,则变为父进程收到一条 {'EXIT', 进程pid,退出理由} 消息。