Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

correct usage of erlang spawn_monitor

Tags:

erlang

Still working through Joe's book, and having hard time fully understanding monitors in general and spawn_monitor in particular. Here's the code I have; the exercise is asking to write a function that will start a process whose job is to print a heartbeat every 5 seconds, and then a function to monitor the above process and restart it. I didn't get to a restart part, because my monitor fails to even detect the process keeling over.

% 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.

And here's me playing with in:

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> 

It sure stopped the loop_5_print "worker" - but where's the line that the monitor was supposed to print? The only explanation that I see is that the message emitted by a process quitting in this manner isn't of the pattern on which I am matching inside monitor loop's receive. But that's the only pattern introduced in the book in this chapter, so I'm not buying this explanation..

like image 214
alexakarpov Avatar asked Sep 27 '17 20:09

alexakarpov


People also ask

How do I end a process in Erlang?

A process can terminate itself by calling one of the BIFs exit(Reason), erlang:error(Reason), erlang:error(Reason, Args), erlang:fault(Reason) or erlang:fault(Reason, Args). The process then terminates with reason Reason for exit/1 or {Reason,Stack} for the others.

How do you spawn a process in Erlang?

You do this by spawning a process using the spawn(Module , Function , Arguments) BIF. This BIF creates a new process that evaluates the Function exported from the module Module with the list of Arguments as parameters. The spawn/3 BIF returns a process identifier, which from now on we will refer to as a pid.

What is pid in erlang?

Every process in Erlang is identified by a unique process identifier (pid). The function self/0 returns the process identifier of the running process. Erlang processes can be created with any of the following functions: spawn, spawn link, spawn monitor, spawn opt, etc.


1 Answers

spawn_monitor is not what you want here. spawn_monitor spawns a process and immediately starts monitoring it. When the spawned process dies, the process that called spawn_monitor gets a message that the process is dead. You need to call erlang:monitor/2 from the process that you want to receive the DOWN messages in, with the second argument being the Pid to monitor.

Just add:

monitor(process, Pid),

after:

Pid = whereis(AName),

and it works:

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
like image 122
Dogbert Avatar answered Sep 18 '22 18:09

Dogbert