Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find the supervisor of an OTP process?

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

like image 805
Alexey Romanov Avatar asked Nov 09 '10 09:11

Alexey Romanov


People also ask

What is supervisor in Erlang?

Supervisors are one of the core things that make Erlang/OTP what it is. An active OTP application consists of one or more processes that do the work. Those processes are started indirectly by supervisors, which are responsible for supervising them and restarting them if necessary.

What is a supervisor in Elixir?

In Elixir, this is done by a Supervisor. A Supervisor is a process that supervises other processes and restarts them whenever they crash. To do so, Supervisors manage the whole life-cycle of any supervised processes, including startup and shutdown.

What does OTP mean Elixir?

What are Elixir and OTP? Elixir is a functional programming language built on the Erlang VM. OTP is a process oriented programming framework integral to Erlang and Elixir.


2 Answers

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.

like image 77
I GIVE TERRIBLE ADVICE Avatar answered Sep 30 '22 10:09

I GIVE TERRIBLE ADVICE


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).
like image 20
YOUR ARGUMENT IS VALID Avatar answered Sep 30 '22 09:09

YOUR ARGUMENT IS VALID