В целях отладки вы можете использовать dbg
:).
Сначала создайте таблицу ets, в которой будут храниться все ссылки на таймеры.
1> ets:new(timer_dbg, ['public', 'named_table', 'bag']).
timer_dbg
Затем создайте функцию-обработчик dbg, котораяпроверяет вызовы, возвращаемые из erlang: send_after, и сохраняет возвращенную ссылку таймера в таблицу
2> Fun = fun({'trace', _Pid, 'return_from', {erlang, send_after, 3}, Ref}, []) ->
2> ets:insert(timer_dbg, {Ref}), [];
2> (_Msg, []) ->
2> []
2> end.
#Fun<erl_eval.12.113037538>
Установить функцию в качестве обработчика трассировки.Также включите сопоставление при вызове к erlang:send_after()
во всех процессах
3> dbg:tracer('process', {Fun, []}).
{ok,<0.35.0>}
4> dbg:p('all', 'c').
{ok,[{matched,nonode@nohost,26}]}
5> dbg:tpl(erlang, send_after, [{'_', [], [{'return_trace'}]}]).
{ok,[{matched,nonode@nohost,1},{saved,1}]}
Сделайте несколько тестовых вызовов к erlang:send_after()
6> erlang:send_after(1000, self(), {}).
#Ref<0.0.0.43>
7> erlang:send_after(1000, self(), {}).
#Ref<0.0.0.47>
8> erlang:send_after(1000, self(), {}).
#Ref<0.0.0.51>
Наконец, убедитесь, что таблица содержит эти ссылки:
9> ets:tab2list(timer_dbg).
[{#Ref<0.0.0.51>},{#Ref<0.0.0.43>},{#Ref<0.0.0.47>}]
Таким образом, вы будете хранить все ссылки на таймеры, когда-либо созданные любым процессом, когда-либо вызывающим erlang:send_after()
.Вы можете сопоставить их с erlang:read_timer()
, чтобы отфильтровать живые таймеры.
Вы можете отследить вызовы на send_after
аналогичным образом.Также можно выполнить поиск по cancel_timer
и вручную удалить отмененные ссылки из таблицы.
Кроме того, если у вас нет приложения с интенсивным обменом сообщениями, вы сможете найти соответствие по сообщениям и /или функции, запускаемые этими таймерами, и удаляют просроченные ссылки из списка.