How to find the supervisor of an OTP process?

前端 未结 2 1365
一生所求
一生所求 2021-01-18 01:45

Are there functions which would allow an OTP process to find the pid of its supervisor?

相关标签:
2条回答
  • 2021-01-18 02:18

    The data is hidden in the process dictionary (of any process spawned with proc_lib) under the entry '$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,[]}]
    

    Here the line that interests us is {dictionary,[{'$ancestors',[<0.31.0>]},.

    Note that this is the kind of stuff you should rarely have any reason to use yourself. As far as I know, it's mostly used to handle clean termination in supervision trees rather than introspection for whatever code you have. Handle with care.

    A cleaner way to do things without messing with OTP's sensible innards would be to have the supervisor pass its own pid as an argument to the process when starting it. This should be far less confusing for the people who'll read your code.

    0 讨论(0)
  • 2021-01-18 02:31

    If you want to do it wrong, here's our solution:

    %% @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).
    
    0 讨论(0)
提交回复
热议问题