2017-08-28 98 views
2

我一直在試圖弄清楚如何在調用進程B中捕獲或救援另一個進程A中的錯誤,該進程也殺死了進程A.如何通過在Elixir中調用進程來捕獲或救援被調用進程的崩潰錯誤

這裏是我的代碼:

defmodule A do 
    def start_link do 
    GenServer.start_link(__MODULE__, :ok, name: :A) 
    end 

    def fun(fun_loving_person) do 
    GenServer.call(fun_loving_person, :have_fun) 
    end 

    def init(:ok) do 
    {:ok, %{}} 
    end 

    def handle_call(:have_fun, _from, state) do 
    raise "TooMuchFun" 
    {:reply, :ok, state} 
    end 
end 

defmodule B do 
    def start_link do 
    GenServer.start_link(__MODULE__, :ok, name: :B) 
    end 

    def spread_fun(fun_seeker) do 
    GenServer.call(:B, {:spread_fun, fun_seeker}) 
    end 

    def init(:ok) do 
    {:ok, %{}} 
    end 

    def handle_call({:spread_fun, fun_seeker}, _from, state) do 
    result = A.fun(fun_seeker) 
    {:reply, result, state} 
    rescue 
    RuntimeError -> IO.puts "Too much fun rescued" 
    {:reply, :error, state} 
    end 
end 

{:ok, a} = A.start_link 
{:ok, _b} = B.start_link 
result = B.spread_fun(a) 
IO.puts "#{inspect result}" 

在模塊B的handle_call功能,我叫模塊A的功能,它在任何情況下塊rescue出現錯誤與過程:A。錯誤提出,但rescue塊未得到執行。

我是否錯過了對一個進程崩潰如何影響另一個的基本理解?只有當錯誤發生在同一過程中時,才嘗試/趕上或嘗試/解救工作?我是否必須監視其他進程並將其退出?

我會感謝您的幫助。

回答

1

在Erlang生態系統中,只有在進程的代碼中引發異常時,纔可以捕獲錯誤,使用try-catch進行出口和拋出,但如果進程以除原子normal之外的任何原因退出,則所有鏈接進程都將收到退出信號,經過出口後,將以{'EXIT', CrashedProcessPid, ReasonOfCrash}的形式收到此信號作爲正常的erlang信息。而另一個沒有陷入退出的進程將會崩潰,原因是ReasonOfCrash和其他鏈接到這些進程的進程將收到signalz等。

+0

謝謝。所以如果我理解你,拋出/拋出錯誤和捕獲/救出它必須發生在同一個過程中? –

+0

是的,必須在同一個進程代碼 – Pouriya

1

您可以通過讓另一個進程監視此進程來完成您喜歡的任務。查看Process.monitor的文檔:https://hexdocs.pm/elixir/Process.html#monitor/1

從本質上講,監測過程將需要處理的信息對於將在崩潰來產生的下行消息:

handle_info({:DOWN, ref, :process, object, reason}, state) do 
    # do something interesting here ... 
end 

請記住,你會想弄清楚什麼reason(S)是你想做這個動作和模式匹配只包含那些。

+0

謝謝。我[修改我的示例代碼](https://gist.github.com/ahmadferdous/a5949e47b604dfda564b10c9461985df)。 B監視A併爲'DOWN消息實現'handle_info'。但是,B不收到:DOWN消息。我仍在研究它。 –

相關問題