2012-02-14 16 views
1

次のプログラムがあります。しかし、生成されたプロセスをトレースすると、以下のトレースに示すようにタイムアウトのトレースメッセージが表示されています。Erlang - ioを呼び出すときにタイムアウトメッセージを受け取る:

start() -> 
    register(addone, spawn(addone, loop, [])). 

loop() -> 
receive 
    {request, Pid, Msg} -> 
     io:format("log ~n", []), 
     loop(); 
    {stop, _Reason} -> 
     stop 
end. 

私は次の関数で、この処理を実行しています:以下のように観察

run() -> 
addone:start(), 
dbg:start(), 
dbg:tracer(), 
dbg:p(whereis(addone), [c,m]), 
dbg:tpl({'_','_','_'},[{'_',['true'],[{'silent', 'false'}]}]), 
addone:request(4). 

トレースは次のとおりです。

1> addone_scenarios:run(). 
log 
(<0.32.0>) << {request,<0.30.0>,4} 
(<0.32.0>) call io:format("log ~n",[]) 
(<0.32.0>) call io:default_output() 
(<0.32.0>) call erlang:group_leader() 
(<0.32.0>) call io:format(<0.23.0>,"log ~n",[]) 
(<0.32.0>) call io:o_request(<0.23.0>,{format,"log ~n",[]},format) 
(<0.32.0>) call io:request(<0.23.0>,{format,"log ~n",[]}) 
(<0.32.0>) call io:io_request(<0.23.0>,{format,"log ~n",[]}) 
(<0.32.0>) call io:bc_req(<0.23.0>,{put_chars,unicode,io_lib,format,["log ~n",[]]},false) 
(<0.32.0>) call net_kernel:dflag_unicode_io(<0.23.0>) 
(<0.32.0>) call io:execute_request(<0.23.0>,{false,{put_chars,unicode,io_lib,format,["log ~n",[]]}}) 
(<0.32.0>) call erlang:monitor(process,<0.23.0>) 
(<0.32.0>) <0.23.0> ! {io_request,<0.32.0>,<0.23.0>, 
          {put_chars,unicode,io_lib,format,["log ~n",[]]}} 
(<0.32.0>) call io:wait_io_mon_reply(<0.23.0>,#Ref<0.0.0.29>) 
(<0.32.0>) << {io_reply,<0.23.0>,ok} 
(<0.32.0>) call erlang:demonitor(#Ref<0.0.0.29>) 
(<0.32.0>) << timeout 
(<0.32.0>) call addone:loop() 

奇妙である何受信されたタイムアウトトレースメッセージです。 io:format(...)を削除すると、このメッセージは受信されません。誰かが理由を教えてくれますか?

EDIT:すべての機能の呼び出しを含めるようにトレースを更新しました。

答えて

0

ここで私の2セントは:dbgのerlang docを読んでも、そのタイムアウトメッセージも表示されます。私の意見では、デバッグメッセージの出力用に登録されたio_serverが、巨大なブロックI/Oトレース、しばらくしても何も追跡されないと、リッスンソケット(メッセージシステムの観点から見て、私はerlangからソケットを意味する)をドロップします。 実際には、印刷サーバーである< 0.23.0>との間のio_requestとio_replyが表示されていますが、それを単に(役に立たない)さらなるデバッグメッセージとして無視することはできます。

+0

私の問題は、プログラムのトレースを解析し、受信したものに基づいて動作するツールを構築していることです。無視できるタイムアウトメッセージは選択できません。残念ながら – aseychell

1

ioモジュールの唯一の場所で、io要求メッセージへの返信を待つ関数io:wait_io_mon_reply/2にタイムアウトがあります。クライアントプロセスがハングしないようにするため、ioプロセスは、応答を返す前に死んでいるケースを検出するために監視されています。 io:wait_io_mon_reply/2は、受信可能なさまざまなケースを処理する必要があります。およびは、複数の戻り値がある場合にメッセージキューをクリーンアップします。たとえば、応答がオフになり、モニタリングがオフになる前にメッセージが送信されます。 erlang通信の非決定論的な非同期性のため、これが起こり、処理しなければなりません。

これを処理する標準的な方法は、(まっすぐな機能から取り出した)ことである:

receive 
    {io_reply, From, Reply} -> 
     erlang:demonitor(Mref), 
     receive 
      {'DOWN', Mref, _, _, _} -> true 
     after 0 -> true 
     end, 
     Reply; 

0のタイムアウトを使用してメッセージがない場合、あなたは待つことはありませんが、あなたはタイムアウトを得るか意味。私はこれがあなたがトレースで見るものだと推測しています。これはエラーではなく、コードが書かれた方法です。このように実行可能な代替手段はありません。

これは、何らかの形でこのタイムアウトを無視するか、プログラムの自然な部分としてタイムアウトを受け入れ、何らかの形の「例外」またはエラーではなく受け入れる必要があることを意味します。

私はそれがどのように機能するか理解しています。

+0

は有効です理由は..おそらく私はちょうどタイムアウトのメッセージを無視する必要があります。 – aseychell

+0

'erlang:demonitor(Mref、[flush])を呼び出すと、代わりにこのタイムアウトを回避できますか?それともそれはまだトレースに表示されますか? – legoscia

+0

この場合は削除する必要がありますが、これは 'io:wait_io_mon_reply/2'のケースの** ** **です。それ以外の場合は役に立ちません。'io'モジュールの機能をチェックしてください。 – rvirding

関連する問題