Erlang gen_server進程花樣做死

本文主要記錄各類狀況下gen_server進程退出的表現。網絡

研究動機起源於Elixir/Phoenix框架中遇到的一個進程異常退出問題。由於網絡異常,客戶端超過一段時間未發來消息,channel進程(一個gen_server)退出了,可是掛的很突兀,不調用 terminate,進而致使掉線處理沒被調用,表現出一堆bug。分析發現它是被shutdown的,而一個gen_server若是沒有trap_exit,被shutdown就不會調用terminate。框架

Anyway,實驗了各類組合,僅以此作個記錄。箇中原因有興趣的能夠閱讀源碼。orm

Process.exit

trap_exit不爲true

當trap_exit不爲true時,Process.exit(Pid, normal) 只有在自身調用時纔會退出,其餘進程中調用不會致使退出。而除normal外的其餘任何一種Reason都會致使進程退出。server

 

trap_exit=true

當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

當trap_exit不爲true時,父進程退出至關於Process.exit(Pid, Reason) 狀況。因爲不是自身調用,normal不會致使子進程死亡,其餘理由均會致使進程死亡,而且不會調用 terminate 回調客戶端

 

trap_exit=true

當trap_exit=true時,全部Reason都會致使進程退出,而且全部Reason都會觸發 terminate 回調。

除 normal 和 shutdown外,其餘Reason均會觸發gen_server的exit log。

 

 

子進程退出對父進程的影響

以上全部的退出方式中,只有退出理由爲 normal ,纔不會往父進程輻射死亡信號。

而父進程收到死亡信號,若是父進程trap_exit不等於true,則會以同一理由隨之死亡並往上傳遞,如trap_exit=true,則變爲父進程收到一條 {'EXIT', 進程pid,退出理由} 消息。

相關文章
相關標籤/搜索