查询Erlang进程的状态?

mwt*_*mwt 15 erlang

Erlang中的一个常见模式是维护状态的递归循环:

loop(State) ->
  receive
    Msg ->
      NewState = whatever(Msg),
      loop(NewState)
  end.
Run Code Online (Sandbox Code Playgroud)

有没有办法用bif或跟踪查询正在运行的进程的状态?由于崩溃消息说"......状态是......"并显示崩溃进程的状态,我认为这很容易,但我很失望,因为我无法找到这样做的bif.

那么,我认为使用dbg模块的跟踪就可以了.不幸的是,我相信因为这些循环是尾调用优化的,所以dbg只捕获对该函数的第一次调用.

有解决方案吗

gle*_*ber 27

如果您的进程使用OTP,那就足够了sys:get_status(Pid).

您提到的错误消息由SASL显示.SASL是OTP中错误报告守护程序.

您在示例代码中引用的状态只是尾递归函数的参数.除了跟踪BIF之外,没有办法使用任何东西来提取它.我想这不是生产代码中的正确解决方案,因为跟踪仅用于调试目的.

正确的,经过行业测试的解决方案将在您的项目中广泛使用OTP.然后,您可以充分利用SASL错误报告,rb模块来收集这些报告,sys- 检查正在运行的OTP兼容流程的状态,proc_lib- 使短期流程符合OTP标准等.


zak*_*rya 5

看起来你是在无中生有地制造问题。erlang:process_info/1 提供了足够的信息用于调试目的。如果您确实需要循环函数参数,为什么不将其返回给调用者以响应您自己定义的特殊消息之一?

更新:只是为了澄清术语。在语言级别上最接近“进程状态”的是进程字典,强烈建议不要使用它。可以通过 erlang:process_info/1 或 erlang:process/2 查询。您实际需要的是跟踪进程的本地函数调用及其参数:

-module(ping).
-export([start/0, send/1, loop/1]).                                                          

start() ->                                                                                   
     spawn(?MODULE, loop, [0]).                                                              

send(Pid) ->                                                                                 
    Pid ! {self(), ping},                                                                    
    receive                                                                                  
    pong ->                                                                                  
         pong                                                                                
    end.                                                                                     

loop(S) ->                                                                                   
    receive                                                                                  
    {Pid, ping} ->                                                                           
        Pid ! pong,                                                                          
        loop(S + 1)                                                                          
    end.                                                                                    
Run Code Online (Sandbox Code Playgroud)

安慰:

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           
Run Code Online (Sandbox Code Playgroud)


Mic*_*rry 5

事实证明,如果您使用OTP,那么答案比所有这些都要好:

sys:get_state/1

可能它当时不存在.