Current section
Files
Jump to
Current section
Files
lib/process_helper.ex
defmodule Tracer.ProcessHelper do
@moduledoc """
Implements helper functions to find OTP process hierarchy
"""
@process_keywords [:all, :processes, :ports, :existing, :existing_processes,
:existing_ports, :new, :new_processes]
@process_keywords |> Enum.each(fn keyword ->
def ensure_pid(unquote(keyword)), do: unquote(keyword)
end)
def ensure_pid(pid) when is_pid(pid), do: pid
def ensure_pid(name) when is_atom(name) do
case Process.whereis(name) do
nil ->
raise ArgumentError,
message: "#{inspect name} is not a registered process"
pid when is_pid(pid) -> pid
end
end
@process_keywords |> Enum.each(fn keyword ->
def type(unquote(keyword)), do: :keyword
end)
def type(pid) do
dict = pid
|> ensure_pid()
|> Process.info()
|> Keyword.get(:dictionary)
case dict do
[] ->
:regular
_ ->
case Keyword.get(dict, :"$initial_call") do
{:supervisor, _, _} -> :supervisor
{_, :init, _} -> :worker
_ -> :regular
end
end
end
@process_keywords |> Enum.each(fn keyword ->
def find_children(unquote(keyword)), do: []
end)
def find_children(pid) do
pid = ensure_pid(pid)
case type(pid) do
:supervisor ->
child_spec = Supervisor.which_children(pid)
Enum.reduce(child_spec, [], fn
{_mod, pid, _type, _params}, acc when is_pid(pid) -> acc ++ [pid]
_, acc -> acc
end)
_ -> []
end
end
@process_keywords |> Enum.each(fn keyword ->
def find_all_children(unquote(keyword)), do: []
end)
def find_all_children(pid) do
pid = ensure_pid(pid)
case type(pid) do
:supervisor ->
find_all_supervisor_children([pid], [])
_ -> []
end
end
def find_all_supervisor_children([], acc), do: acc
def find_all_supervisor_children([sup | sups], pids) do
{s, p} = sup
|> Supervisor.which_children()
|> Enum.reduce({[], []}, fn
{_mod, pid, :supervisor, _params}, {s, p} when is_pid(pid) ->
{s ++ [pid], p ++ [pid]}
{_mod, pid, _type, _params}, {s, p} when is_pid(pid) ->
{s, p ++ [pid]}
_, acc -> acc
end)
find_all_supervisor_children(sups ++ s, pids ++ p)
end
end