本文主要記錄各類狀況下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,退出理由} 消息。