2012-02-14 28 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(...)时,未收到此消息。有人可以指出什么是可能的原因吗?

编辑:我已更新跟踪以包含所有功能的调用,也许它可能有所帮助。

回答

0

我的两分钱在这里:如果您阅读erlang doc for dbg,您也会看到该超时消息,我认为注册打印调试消息的io_server产生了一个专用的进程,可以缓解大型阻塞I/O跟踪的性能,但过了一段时间,没有任何东西被追踪,它只是放弃侦听的“套接字”(我的意思是从erlang传递消息系统的角度来看套接字)。 你的确看到io_request和io_reply并从< 0.23.0>是打印服务器,我想你可以简单地忽略它作为一个(无用)进一步调试消息。

+0

我忽略这个跟踪消息的问题是,我正在构建一个工具来分析程序的痕迹,并根据它收到的内容采取行动..所以我不能选择哪些超时消息我可以忽略,哪些不是不幸的 – aseychell 2012-02-14 18:09:38

1

在IO模块,其中有在功能io:wait_io_mon_reply/2其中它等待回复到IO请求消息超时中的唯一位置。为了确保客户端进程不会挂起,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 2012-02-14 23:40:48

+0

会调用'erlang:demonitor(Mref,[flush])'而不是避免这个超时?或者它仍然会出现在痕迹中? – legoscia 2012-02-15 14:30:53

+0

在这种情况下,它应该将其删除,但这仅仅是'io:wait_io_mon_reply/2'中的**一个**,并且在其他情况下不起作用。查看'io'模块中的函数。 – rvirding 2012-02-16 23:43:58