以前も例外処理を扱いましたが、今回は並列処理における例外です。
並列処理における例外はおもに、プロセス間の対応付けによって決まります。 その手法は link と monitor が主なものです。 他にはOTP(Open Telecom Platform)を使ったものもあるのですが、それは別の章で扱います。
この章では簡単なlinkを使って例外処理を学びます。 したがいまして、linkは次の章と合わせての2本立てという構成になります。
それでは、実際に例外処理について見ていきましょう。
Erlangのプロセスの終了にはおもに2通りあります。
です。
異常処理を修復するためには、まず異常終了をしたということ知る必要がありますね。 その後に、なんらかの処理に移るというわけです。
link や monitor はこの異常終了の検知に使われます。
異常終了の行なったプロセスは、自分と関係のある(link,monitorされている)プロセスに対して、 終了シグナルを送信します。
この終了シグナルを通じて、関係のあるプロセスの死亡を知らされるわけです。
終了シグナルを受け取ったプロセスは、それ自身も死亡します。(死亡しない方法は後述)
linkは2つのプロセスに関係を持たせる時に利用します。 片方が死んだときに、もう片方に対して終了シグナルを送信するようになるということです。
書式は簡単で
link(Pid)
とするだけです。
これで、この関数を呼び出したプロセスと、Pidで指定されたプロセスはリンクで繋がれます。
それでは、実際にプログラムを通して確認してみましょう。
-module(addserver).
-export([start_server/0, start_handler/1]).
start_server() ->
spawn(fun() -> server_loop() end).
server_loop() ->
receive
{add,X,Y} ->
io:format("~p~n",[X + Y]),
server_loop()
end.
start_handler(Pid) ->
spawn(fun() -> handler(Pid) end).
handler(Pid) ->
link(Pid),
handler_loop(Pid).
handler_loop(Pid) ->
receive
Message ->
Pid ! Message,
handler_loop(Pid)
end.
このプログラムを試してみます。
構成としては、サーバーが2つ存在します。一つは実際に処理を行なうサーバで、もう一つはそれとユーザを仲介するサーバと言えます。
今回は、処理サーバと仲介サーバをリンクで繋ぎ、処理サーバをわざとクラッシュさせます。 リンクが成功しているのであれば、処理サーバがクラッシュした際に終了シグナルを仲介サーバに対して送信するので、 仲介サーバも死亡します。
なお、is_process_alive(Pid)はプロセスが生きているかどうかを調べる関数です。
生きていれば true 、死んでいれば false を返します。
処理用のサーバ
3> Pid = addserver:start_server().
<0.35.0>
仲介サーバ
4> Handler = addserver:start_handler(Pid).
<0.37.0>
普通に処理
5> Handler ! {add,3,8}.
11
{add,3,8}
6> is_process_alive(Handler).
true
処理サーバをわざと殺す。
7> Handler ! {add,dog,cat}.
{add,dog,cat}
=ERROR REPORT==== 14-May-2008::22:28:57 ===
Error in process <0.35.0> with exit value: {badarith,[{addserver,server_loop,0}]}
仲介サーバも死んでいる。
8> is_process_alive(Handler).
false
リンクは成功したようです。
プロセスの終了には2種類(健全な終了と異常な終了)があるという話はしました。
実は終了シグナルもこれに習って2種類存在します。
の2つです。Reasonは normal 以外のアトムです。
exit()については、逐次処理の例外処理編でも扱いました。 プロセスを終了したいエラーの際に呼び出されるのでしたね。任意で呼び出すことも可能です。
exit(normal)は通常終了の際に使われます。これを用いた際はリンクされているプロセスは死にません。
exit(Reason)は異常終了です。これを用いた場合はリンクされているプロセスは死にます。
次の節では、システムプロセスを扱います。 これを用いると、終了シグナルを受け取っても自分は終了しなくなります。