2010-11-09 2 views

ответ

12

Данные скрыты в словаре процесса (любой процесс породившего с 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 в качестве аргумента для процесса при запуске. Это должно быть гораздо менее запутанным для людей, которые прочтут ваш код.

+0

Да, это выглядит неплохо. –

+3

Я бы тоже пошел с проходом диспетчера pid. Его проще внедрять и поддерживать. –

1

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

%% @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). 
Смежные вопросы