Как найти супервизора процесса OTP? - PullRequest
7 голосов
/ 09 ноября 2010

Существуют ли функции, которые позволят процессу OTP найти pid своего супервизора?

Ответы [ 2 ]

12 голосов
/ 09 ноября 2010

Данные скрыты в словаре процессов (любого процесса, порожденного proc_lib) под записью '$ancestors':

1> proc_lib:spawn(fun() -> timer:sleep(infinity) end).
<0.33.0>
2> i(0,33,0).
[{current_function,{timer,sleep,1}},
 {initial_call,{proc_lib,init_p,3}},
 {status,waiting},
 {message_queue_len,0},
 {messages,[]},
 {links,[]},
 {dictionary,[{'$ancestors',[<0.31.0>]},
              {'$initial_call',{erl_eval,'-expr/5-fun-1-',0}}]},
 {trap_exit,false},
 {error_handler,error_handler},
 {priority,normal},
 {group_leader,<0.24.0>},
 {total_heap_size,233},
 {heap_size,233},
 {stack_size,6},
 {reductions,62},
 {garbage_collection,[{min_bin_vheap_size,46368},
                      {min_heap_size,233},
                      {fullsweep_after,65535},
                      {minor_gcs,0}]},
 {suspending,[]}]

Здесь строка, которая нас интересует, - {dictionary,[{'$ancestors',[<0.31.0>]},.

Заметьте, что это тот тип вещей, который вы редко должны иметь для себя.Насколько я знаю, он в основном используется для обработки чистого завершения в деревьях контроля, а не для самоанализа любого кода, который у вас есть.Обращайтесь с осторожностью.

Более чистый способ сделать все, не мешая разумным внутренностям OTP, - это заставить супервизор передать свой собственный pid в качестве аргумента процессу при запуске .Это должно быть гораздо менее запутанным для людей, которые будут читать ваш код.

1 голос
/ 10 ноября 2010

Если вы хотите сделать это неправильно, вот наше решение:

%% @spec get_ancestors(proc()) -> [proc()]
%% @doc Find the supervisor for a process by introspection of proc_lib
%% $ancestors (WARNING: relies on an implementation detail of OTP).
get_ancestors(Pid) when is_pid(Pid) ->
    case erlang:process_info(Pid, dictionary) of
        {dictionary, D} ->
            ancestors_from_dict(D);
        _ ->
            []
    end;
get_ancestors(undefined) ->
    [];
get_ancestors(Name) when is_atom(Name) ->
    get_ancestors(whereis(Name)).

ancestors_from_dict([]) ->
    [];
ancestors_from_dict([{'$ancestors', Ancestors} | _Rest]) ->
    Ancestors;
ancestors_from_dict([_Head | Rest]) ->
    ancestors_from_dict(Rest).
...