iT邦幫忙

DAY 16
1

蠻可愛的 Erlang 與 Elixir系列 第 16

Concurrent程式設計之Processes錯誤狀況處理

  • 分享至 

  • xImage
  •  

前面我們看過產生processes及之間的通訊.
那當process發生錯誤時,是怎樣的處理機制呢?

我們先來看一個BIF(內建函數),叫link/1.

簡單範例如下:

-module(e1016a).
-export([sleeper/0]).

sleeper() ->
  timer:sleep(30000),
  % slepp 30 seconds
  exit(resaon_wakeup).

執行過程:

1> c(e1016a).
{ok,e1016a}
2> Pid = spawn(fun e1016a:sleeper/0). 
<0.35.0>
3> link(Pid).
true
** exception error: resaon_wakeup

解說:

如上圖所示,erlang shell透過link/1連結sleeper,
當sleeper離開時,會將訊息傳送給erlang shell.

接著我們來看命運的鎖鏈....

-module(e1016b).
-export([fate/1]).

fate(0) ->
  receive
    _ -> ok
  after 5000 ->
    exit("Bye! Bang!!")
  end;
fate(N) ->
  Pid = spawn(fun() -> fate(N-1) end),
  link(Pid),
  receive
    _ -> ok
  end.

編譯及執行:

1> c(e1016b).
{ok,e1016b}
2> link(spawn(e1016b, fate, [3])).
true
** exception error: "Bye! Bang!!"

解說:
使用spawn/3來產生, 格式為 spawn(Module, Fun, Args), Args = [terms]
透過遞迴方式,依序產生process,並且link.

整個過程如下:

shell ==link==> fate(3) ==link==> fate(2) ==link==> fate(1) ==link==> fate(0) 
shell ==link==> fate(3) ==link==> fate(2) ==link==> fate(1) ==link==> Bye! Bang!!
shell ==link==> fate(3) ==link==> fate(2) ==link==> Bye! Bang!!
shell ==link==> fate(3) ==link==> Bye! Bang!!
shell ==link==> fate(3) Bye! Bang!!
shell ==link==> Bye! Bang!!
shell dead and show reason:Bye! Bang!!
shell 重啟!

透過 link 連接的雙方,當一方exit或dead時,另一方也會受到影響.
這樣子的機制似乎不太理想.
實際上,我們不會這樣子讓一個process把整個系統弄垮.
我們接著來看,要怎樣處理.

捕捉信號的機制.

1> link(spawn(e1016b, fate, [3])).
true
2> receive X -> X end.
{'EXIT',<0.36.0>,"Bye! Bang!!"}

透過上面的過程,可以看到Shell 使用 receive 捕捉到 exit的訊息.
shell依然存活.
可以觀察到格式為tuple, {'EXIT', Pid, Reason}.

這樣我們就可以依據exit的訊息格式,捕捉後做適當處理.


上一篇
Concurrent的receive with timeout以及註冊process
下一篇
Concurrent程式設計之捕捉process離開信號 #1
系列文
蠻可愛的 Erlang 與 Elixir30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言