分かってしまえば、ものすごくシンプルなんだけど、simpledungeon開発中にハマッた件。
Erlang/OTPの、supervisor ビヘイビアで、start_linkに渡すスーパバイザ名と、start_childに渡すスーパバイザ名の書き方に違いがあるということに気づかず、謎のエラーが出続けて1週間ほどタイムロスしてました。
●スーパバイザの起動
supervisor:start_link({local,?MODULE},?MODULE,[])
のように書いたわけです。この記述には問題はありません。
●子プロセスであるyawsを起動するところ
子プロセスの起動側に問題がありました。
誤:[supervisor:start_child({local,?MODULE}, Ch) || Ch <- ChildSpecs]
正:[supervisor:start_child(?MODULE, Ch) || Ch <- ChildSpecs]
ずっと、誤の書き方をしていて、下のようなエラーメッセージが出続けていました。なんでnodedownやねん、と。このエラーメッセージの原因が分からなかったわけです(相対ディレクトリ指定ができないのかなとか、どっかがリストになってないのかな、とか)。でも、全然原因は違ってました。。。
=エラーメッセージ:=============
1> simpledungeon:start().
** exception exit: {{nodedown,simpledungeon},
{gen_server,call,
[{local,simpledungeon},
{start_child,
{yaws_log,
{yaws_log,start_link,[]},
permanent,5000,worker,
[yaws_log]}},
infinity]}}
in function gen_server:call/3
in call from simpledungeon:'-start_yaws/0-lc$^0/1-0-'/1
in call from simpledungeon:start_yaws/0
in call from simpledungeon:start/0
2>
===================
原因はシンプルで、start_childの第1引数には、start_linkのときに指定していた{local, 名称}タプルではなく、名前のアトムを渡さないといけなかったのですね。
http://www.erlang.org/doc/man/supervisor.html
にある、supervisor:start_child/2の定義。
=======================
start_child(SupRef, ChildSpec) -> Result
Types:
SupRef = Name | {Name,Node} | {global,Name} | pid()
Name = Node = atom()
ChildSpec = child_spec() | [term()]
Result = {ok,Child} | {ok,Child,Info} | {error,Error}
Child = pid() | undefined
Info = term()
Error = already_present | {already_started,Child} | term()
=======================
SupRefが、「どのスーパバイザに子プロセスを起動させるか」の参照なわけですが、{global,Name}がある一方で、{local,Name}はなく、そのかわりにNameがあるわけです。
というわけで、スーパバイザとスーパバイズ対象の子プロセスをどちらもローカルで立ち上げるのであれば、start_linkでは{local, Name}を指定し、start_childではNameを渡すという起動方法になる、、、のですよ。
はまった。
2011年04月18日
この記事へのコメント
seiko リザルト
Posted by ck ブランド at 2013年09月25日 17:31
腕時計 会社
Posted by セイコー at 2013年09月25日 17:31
armani ネックレス
Posted by セイコー ブレスレット at 2013年09月25日 17:31
コメントを書く
この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/44407840
この記事へのトラックバック
http://blog.sakura.ne.jp/tb/44407840
この記事へのトラックバック