gen_server с именем timer_server приводил к тому, что функции модуля таймера не возвращались
Вопрос
Я создал супервизора, который породил gen_server
Я позвонил timer_server
.Одна из задач этого timer_serve
r — управлять регистрацией и звонить timer:send_interval
отправить сообщение pid через определенный интервал.
Однако в начале gen_server
, куда я звоню timer:send_interval
Меня заблокировали.В документации указано, что таймер:функции возвращаются немедленно, поэтому это очень беспокоило.
Когда я переименовал свой gen_server
к record_timer_server
эта проблема прояснилась.Тогда мой вопрос двоякий:
- Почему я мог создать зарегистрированный процесс
timer_server
, если такой уже был, когдаtimer:start()
был вызван при запуске моего приложения? - После запуска, почему эта функция не может привести к некорректному поиску имени, если она звонит на мой
timer_server
используяsend_interval
функция?
Я не думаю, что код необходим, но я могу обновить его и добавить, если потребуется.
Решение
Это можно воссоздать, просто выполнив следующую команду, которая зависает при вызове таймера: send_interval.
1> register(timer_server, self()).
true
2> timer:send_interval(5000, self(), hello).
Пока это не удается...
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>]},
Итак, похоже, что первый вызов таймера пытается запустить процесс с именем timer_server и зависает, если вы сначала взяли это имя.
Что касается того, почему он зависает, timer.erl делает:
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.
который возвращает штраф, за которым следует gen_server:вызов timer_server.Затем ваш процесс застревает в ожидании ответа.