正确使用erlang spawn_monitor

ale*_*pov 3 erlang

仍在使用Joe的书,并且很难完全理解一般的监视器,特别是spawn_monitor.这是我的代码; 练习要求编写一个函数,该函数将启动一个进程,其工作是每5秒打印一次心跳,然后是一个监视上述进程并重新启动它的函数.我没有进入重启部分,因为我的显示器甚至无法检测到过程中的过程.

% simple "working" loop
loop_5_print() ->
    receive
    after 5000 ->
            io:format("I'm still alive~n"),
            loop_5_print()
    end.

% function to spawn and register a named worker
create_reg_keep_alive(Name) when not is_atom(Name) ->
    {error, badargs};
create_reg_keep_alive(Name) ->
    Pid = spawn(ex, loop_5_print, []),
    register(Name, Pid),
    {Pid, Name}.

% a simple monitor loop
monitor_loop(AName) ->
    Pid = whereis(AName),
    io:format("monitoring PID ~p~n", [Pid]),
    receive
        {'DOWN', _Ref, process, Pid, Why} ->
            io:format("~p died because ~p~n",[AName, Why]),
            % add the restart logic
            monitor_loop(AName)
    end.

% function to bootstrapma monitor
my_monitor(AName) ->
    case whereis(AName) of
        undefined -> {error, no_such_registration};

        _Pid -> spawn_monitor(ex, monitor_loop, [AName])
    end.
Run Code Online (Sandbox Code Playgroud)

这是我玩的:

39> c("ex.erl").                    
{ok,ex}
40> ex:create_reg_keep_alive(myjob).
{<0.147.0>,myjob}
I'm still alive                     
I'm still alive          
41> ex:my_monitor(myjob).
monitoring PID <0.147.0>
{<0.149.0>,#Ref<0.230612052.2032402433.56637>}
I'm still alive
I'm still alive                     
42> exit(whereis(myjob), stop).
true
43> 
Run Code Online (Sandbox Code Playgroud)

它确实停止了loop_5_print "worker" - 但显示器应该打印的行在哪里?我看到的唯一解释是,以这种方式退出的进程发出的消息不是我在监视器循环接收内匹配的模式.但这是本章书中介绍的唯一模式,所以我不买这个解释.

Dog*_*ert 6

spawn_monitor这不是你想要的.spawn_monitor生成一个进程并立即开始监视它.当生成的进程终止时,调用的进程spawn_monitor会收到一条消息,指出进程已经死亡.您需要erlang:monitor/2从要接收DOWN消息的进程中调用,第二个参数是要监视的Pid.

只需添加:

monitor(process, Pid),
Run Code Online (Sandbox Code Playgroud)

后:

Pid = whereis(AName),
Run Code Online (Sandbox Code Playgroud)

它有效:

1> c(ex).
{ok,ex}
2> ex:create_reg_keep_alive(myjob).
{<0.67.0>,myjob}
I'm still alive
I'm still alive
I'm still alive
3> ex:my_monitor(myjob).
monitoring PID <0.67.0>
{<0.69.0>,#Ref<0.2696002348.2586050567.188678>}
I'm still alive
I'm still alive
I'm still alive
4> exit(whereis(myjob), stop).
myjob died because stop
true
monitoring PID undefined
Run Code Online (Sandbox Code Playgroud)