2010-11-09 9 views

risposta

12

I dati è nascosta nel dizionario di processo (di qualsiasi processo generato con proc_lib) alla voce '$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,[]}] 

Qui la linea che ci interessa è {dictionary,[{'$ancestors',[<0.31.0>]},.

Si noti che questo è il tipo di cose che raramente dovresti avere una ragione per usarti. Per quanto ne so, è principalmente usato per gestire la terminazione pulita negli alberi di supervisione piuttosto che l'introspezione per qualunque codice tu abbia. Maneggiare con cura.

Un modo più pulito di fare le cose senza intaccare le viscere sensibili di OTP sarebbe quello di fare in modo che il supervisore passi il proprio pid come argomento al processo quando lo avvia. Questo dovrebbe essere molto meno confuso per le persone che leggeranno il tuo codice.

+0

Sì, sembra una buona idea. –

+3

Anch'io vado con il pass del supervisore pid. È più semplice da implementare e mantenere. –

1

Se si vuole fare male, ecco la nostra soluzione:

%% @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). 
Problemi correlati