Pregunta

¿Hay funciones que permitan un proceso de OTP para encontrar el PID de su supervisor?

¿Fue útil?

Solución

Los datos se oculta en el diccionario proceso (de cualquier proceso generado con proc_lib) bajo el '$ancestors' entrada:

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,[]}]

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

Tenga en cuenta que este es el tipo de cosas que usted debe rara vez tienen ninguna razón para utilizar usted mismo. Por lo que yo sé, se utiliza sobre todo para manejar la terminación limpia en los árboles de supervisión en lugar de la introspección por cualquier código que tiene. Manipular con cuidado.

Una forma más limpia de hacer las cosas sin jugar con entrañas sensibles de OTP sería tiene el supervisor aprobar su propia PID como un argumento para el proceso al arrancar . Esto debería ser mucho menos confuso para la gente que va a leer su código.

Otros consejos

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).
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top