tags:

views:

175

answers:

1

I created a supervisor that spawned a gen_server I called timer_server. One of the tasks of this timer_server is to manage registration and call timer:send_interval to send a message to a pid on a certain interval.

However, in the init of the gen_server, where I call timer:send_interval I was getting a lockup. The documentation said the timer: functions return immediately, so this was very troubling.

When I renamed my gen_server to record_timer_server this problem cleared up. My question is two fold then:

  1. Why could I create a registered process timer_server, if there already was one when timer:start() was called by my application starting up?
  2. Once started, why would this function not cause a badmatch finding the name, if it was calling in to my timer_server using the send_interval function?

I don't think code is necessary but I can update to add some if requested.

+3  A: 

This can be recreated simply by doing the following which hangs on the call to timer:send_interval.

1> register(timer_server, self()).
true
2> timer:send_interval(5000, self(), hello).

While this fails...

1> timer:send_interval(5000, self(), hello).
{ok,{interval,#Ref<0.0.0.32>}}
2> register(timer_server, self()).
** exited: {badarg,[{erlang,register,[timer_server,<0.30.0>]},

So, it seems that the first call to timer tries to start a process called timer_server, and hangs if you've taken this name first.

As to why it hangs timer.erl does:

ensure_started() ->
    case whereis(timer_server) of
        undefined -> 
            C = {timer_server, {?MODULE, start_link, []}, permanent, 1000, 
                worker, [?MODULE]}
            supervisor:start_child(kernel_safe_sup, C),  % kernel_safe_sup
            ok;
        _ -> ok
    end.

which returns fine, followed by a gen_server:call to timer_server. Your process then gets stuck waiting for itself to respond.

cthulahoops
thank you, that makes total sense.
Rob Elsner