2010年01月16日

spawnは慣れるまで「spawn_link」で書かないといけませんね

Erlangで、別プロセスへのメッセージ送信の練習をするのだ−、ということで、メッセージ受信部をspawnしておいて、そのあとメッセージを連投する、というコードを書いてみたのですが、なぜかreceiverのio:formatが受信したメッセージを表示してくれないという現象で一晩ハマりました。

バグとしては単純で、io:formatの追加引数のところをリスト化し忘れていたために表示されなかったのですが、まったくエラーとかが出なかったのでハマッたわけです。

結局、spawnをspawn_linkに置き換えて、生成したプロセスがエラーを発生させて止まったときに、親のプロセスも止まるようにしたら、エラーメッセージが出て原因箇所がつきとめられました。

親に影響が波及しては困るプロセス生成もあるのでしょうけど、そんなのは先の話。ひとまず初心者のうちはspawn_linkと書くようにしますー

--[期待した出力]--------
1> c(procs).
{ok,procs}
2> procs:testit().
Message from 5
Message from 4
Message from 3
Message from 2
Message from 1
ok
3>
-------------------------

--[実際の出力]-----------
1> c(procs).
{ok,procs}
2> procs:testit().
ok
3>
-------------------------


--[spawn_linkに置き換えたときの出力]-----------
10> procs:testit().
Message send 5
Message send 4
Message send 3
** exception exit: badarg
in function io:format/3
called as io:format(<0.25.0>,"Message from ~p~n",5)
in call from procs:receiver/0
11>
-----------------------------------------------


--[動かなかったコード]-----------------------
-module(procs).
-compile(export_all).

testit() ->
Pid = prep(),
timer:sleep(3000),
kicktest(Pid, 5).

prep()->
spawn(?MODULE, receiver,[]).

receiver() ->
receive
{num, A} ->
io:format("Message from ~p~n", A),
receiver();
{stop} ->
io:format("bye ~n");
_Other ->
io:format("Unknown message~n"),
receiver()
end.

kick(Pid, A) ->
Pid ! {num, A}.

kicktest(_ReceiverPid, 0)
-> ok;

kicktest(ReceiverPid, Count) when Count > 0 ->
kick(ReceiverPid, Count),
kicktest(ReceiverPid, Count -1).

-----------------------------------

--[ちゃんと動くコード]-----------------------
-module(procs).
-compile(export_all).

testit() ->
Pid = prep(),
timer:sleep(3000),
kicktest(Pid, 5).

prep()->
spawn(?MODULE, receiver,[]).

receiver() ->
receive
{num, A} ->
% ここ、Aをリスト化し忘れてた↓
io:format("Message from ~p~n", [A]),
receiver();
{stop} ->
io:format("bye ~n");
_Other ->
io:format("Unknown message~n"),
receiver()
end.

kick(Pid, A) ->
Pid ! {num, A}.

kicktest(_ReceiverPid, 0)
-> ok;

kicktest(ReceiverPid, Count) when Count > 0 ->
kick(ReceiverPid, Count),
kicktest(ReceiverPid, Count -1).

-----------------------------------

posted by へろ at 13:06| Comment(0) | TrackBack(0) | Erlang
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/34772981

この記事へのトラックバック