まず最初にシステムプロセスについて扱います。
システムプロセスは特殊なプロセスです。その特徴として、 終了シグナルが送られても自分は終了しないという機能を持っています。
正確に言うのであれば、「終了シグナルが終了メッセージになる」と言えるかもしれません。
なぜならば、システムプロセスにおいては終了シグナルは単なるメッセージだからです。
従って、receive文で受け取ることが可能となります。
ちなみに、今までの終了シグナルはメッセージとして送られて来て、プロセスのメールボックスに格納された途端に プロセスを終了させていました。
プロセスをシステムプロセスにするには以下のようにすれば大丈夫です。
process_flag(trap_exit,true)
process_flagという関数を使うのですね。
それでは、実際にプログラムを通して確認していきましょう。
-module(addserver2).
-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) ->
process_flag(trap_exit,true),
link(Pid),
handler_loop(Pid).
handler_loop(Pid) ->
receive
{send, Message} ->
Pid ! Message,
handler_loop(Pid);
Other ->
io:format("Receive in handler : ~p~n",[Other]),
handler_loop(Pid)
end.
前回のプログラムと異なる点は、仲介プロセスをシステムプロセスにして、 なおかつ終了メッセージを表示するようにしてあるという点です。
1> Pid = addserver2:start_server().
<0.33.0>
2> Handler = addserver2:start_handler(Pid).
<0.35.0>
3> Handler ! {send,{add,4,3}}.
7
{send,{add,4,3}}
4> is_process_alive(Handler).
true
5> Handler ! {send,{add,dog,cat}}.
Receive in handler : {'EXIT',<0.33.0>,{badarith,[{addserver2,server_loop,0}]}}
{send,{add,dog,cat}}
6>
=ERROR REPORT==== 14-May-2008::22:58:22 ===
Error in process <0.33.0> with exit value: {badarith,[{addserver2,server_loop,0}]}
6> is_process_alive(Handler).
true
仲介サーバがシステムプロセスなので、終了メッセージを捕捉していますね。
さらに、仲介サーバも死んでいないことが確認できました。
例外処理で用いられる関数の一覧です。なお、モニターのものについては次の節で扱います。
関数(BIF erlang) | 役割 |
---|---|
link(Pid) | 呼び出し元と、Pidプロセスとの間にリンクを作成する。Pidが生きていればtrueを返す。 process_flag(trap_exit,true)が呼び出された状態で、Pidが死んでいればtrueを返し、同時に終了シグナルを受ける。 process_flag(trap_exit,true)が呼び出されていない状態で、Pidが死んでいれば例外を投げる。 |
unlink(Pid) | Pidとのリンクをを解除する。Pidが生きていようと死んでいようとtrueを返す。 |
spawn_link(Fun) | 新しいプロセスを作成すると同時にリンクを作成し、その識別子供を返す。
プロセス作成とリンクの作成は同時に実行され、決して分離されることはない。 つまり、spawn(Fun),link(Pid)とは異なる。 |
spawn_link(Node, Fun) | ノードNodeに新しいプロセスをFun/0から作成し同時にリンクを作成する。 そして、その識別子を返す。 |
spawn_link(Module, Function, Args) | モジュールModuleの関数Function(Args)を新しいプロセスとしてスタートさせ、同時にリンクを作成する。 そして、その識別子を返す |
spawn_link(Node, Module, Function, Args) | ノードNodeにモジュールModuleの関数Function(Args)を新しいプロセスとしてスタートさせ、 同時にリンクを作成する。そして、その識別子を返す |
process_flag(trap_exit, Value) | Valueがtrueならシステムプロセスとなり、falseならシステムプロセスでなくなる。 デフォルトはfalseである。 |
exit(Why) | Whyを原因として自分のプロセスを終了させ、リンクされているプロセスに異常終了を伝える |
exit(Pid,Why) | Pidに対して、自分が異常終了で死んだと伝える。自分自身は死なない。 |