3

I have been trying to monitor a gen_server using erlang:monitor/2. Unfortunately every time I try this the Erlang shell goes into an infinite loop.

Here is the test program i've written to test this out.

-module(testmon).

-compile(export_all).

start() ->
    {ok,Proc} = gen_server:start(calc,[],[]),
    erlang:monitor(process,Proc),
    receive
        {'DOWN', Ref, process, Pid,  normal} -> 
            io:format("~p said that ~p died by natural causes~n",[Ref,Pid]);
        {'DOWN', Ref, process, Pid,  Reason} ->
            io:format("~p said that ~p died by unnatural causes~n~p",[Ref,Pid,Reason])
    end.

When I use the above code to monitor something like this spawn(fun() -> ok end) (by changing lines 6 and 7) to erlang:monitor(spawn(fun() -> ok end)) the above code works as intended.

Can someone please show me what i am doing wrong? Is it only possible to monitor a gen_server process via a supervisor?

Thank you

Brendan Cutajar
  • 697
  • 6
  • 14
  • Seems like you have done a copy and paste error in your code. Also adding an 'after 1000 -> timeout' clause at the end might help you debug. – Lukas Mar 19 '12 at 18:56
  • 1st and 2nd line of start function ?? 1st is pure syntax err.. – user425720 Mar 19 '12 at 20:43
  • Fixed: You are correct I accidentally messed up the code when pasting it. This is what I originally intended it to be. Thank you – Brendan Cutajar Mar 19 '12 at 21:50
  • If the started `gen_server` doesn't terminate then the `receive` will wait for ever, unless you add a timeout as @Lukas suggested. What do you mean by "infinite loop"? Do you just mean that the shell never returns? – rvirding Mar 20 '12 at 01:47
  • By infinite loop i mean that the shell never returns. When I added the after clause I did receive a timeout. From what you guys are saying i can deduce that what is really happening is that the gen_server is starting correctly and since the gen_server will not stop unless it is terminated (normally or abnormally) the monitor will never leave the receive section thus the shell will never return. Am I correct in these deductions? – Brendan Cutajar Mar 20 '12 at 06:45
  • Yes, that is what is happening. That is why I asked about infinite loop as it is not looping, but just sitting there waiting. – rvirding Mar 20 '12 at 14:10
  • So the my next question would be the following. What would be the best strategy to monitor a gen_server type application? I would like to be informed as soon as the server is down and the reason why it went down using monitors. – Brendan Cutajar Mar 21 '12 at 07:08

1 Answers1

4

It's not an infinite loop (there are no loops in Erlang at all), your shell just blocks in receive until the gen_server dies for some reason. If you want shell to return immediately just spawn an additional process to do the monitoring. It does not have to be gen_supervisor, your code in separate process should walk as intended.

This can look something like this:

-module(testmon).

-compile(export_all).

start() ->
    {ok,Proc} = gen_server:start(calc,[],[]),
    spawn(?MODULE, monitor, [Proc]).

monitor(Proc) ->
    erlang:monitor(process,Proc),
    receive
        {'DOWN', Ref, process, Pid,  normal} -> 
            io:format("~p said that ~p died by natural causes~n",[Ref,Pid]);
        {'DOWN', Ref, process, Pid,  Reason} ->
            io:format("~p said that ~p died by unnatural causes~n~p",[Ref,Pid,Reason])
    end.
Ivan Blinkov
  • 2,466
  • 15
  • 17