2010-11-09 5 views

Respuesta

12

Los datos se oculta en el diccionario proceso (de cualquier proceso dio con proc_lib) bajo la entrada '$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,[]}] 

Aquí la línea que nos interesa es {dictionary,[{'$ancestors',[<0.31.0>]},.

Tenga en cuenta que este es el tipo de cosas que rara vez debe tener alguna razón para usar usted mismo. Hasta donde yo sé, se usa principalmente para manejar la terminación limpia en árboles de supervisión en lugar de la introspección para cualquier código que tenga. Tratar con cuidado.

Una manera más limpia de hacer las cosas sin meterse con las entrañas sensibles de OTP sería hacer que el supervisor pase su propio pid como argumento del proceso al iniciarlo. Esto debería ser mucho menos confuso para las personas que leerán su código.

+0

Sí, parece una buena idea. –

+3

Me gustaría ir con el pase del supervisor pid también. Es más simple de implementar y mantener. –

1

Si desea hacerlo mal, aquí está nuestra solución:

%% @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). 
Cuestiones relacionadas