title: Storing supervisor children PIDs
body: <p>I'm Erlang beginner and trying to implement my first Erlang application. It is a network monitor tool which should execute ping request to specified host. Actually sending ICMP is not an aim, I'm more interested in application structure. Currently I have monitor_app, monitor_sup (root sup), pinger_sup and pinger (worker). This is pinger_sup:</p>
  
  <pre><code>-module(pinger_sup).
  -behaviour(supervisor).
  -export([start_link/0, start_child/1, stop_child/1]).
  -export([init/1]).
  
  start_link() -&gt;
      supervisor:start_link({local, ?MODULE}, ?MODULE, []).
  
  start_child(Ip) -&gt;
      {ok, Pid} = supervisor:start_child(?MODULE, Ip),
      put(Pid, Ip),
      {ok, Pid}.
  
  stop_child(Ip) -&gt;
      Children = get_keys(Ip),
      lists:foreach(fun(Pid) -&gt;
              pinger:stop(Pid)
          end,
          Children).
  
  init(_Args) -&gt;
      Pinger = {pinger, {pinger, start_link, []},
          transient, 2000, worker, [pinger]},
      Children = [Pinger],
      RestartStrategy = {simple_one_for_one, 4, 3600},
      {ok, {RestartStrategy, Children}}.
  </code></pre>
  
  <p>And pinger itself:</p>
  
  <pre><code>-module(pinger).
  -behaviour(gen_server).
  -export([start_link/1, stop/1, stop_ping/1, ping/1, ping/2]).
  -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
  -define(PING_INTERVAL, 5000).
  
  start_link(Ip) -&gt;
      gen_server:start_link(?MODULE, Ip, []).
  
  stop(Pid) -&gt;
      gen_server:cast(Pid, stop).
  
  stop_ping(Ip) -&gt;
      pinger_sup:stop_child(Ip).
  
  ping(Ip) -&gt;
      pinger_sup:start_child(Ip).
  
  ping(_Ip, 0) -&gt;
      ok;
  ping(Ip, NProc) -&gt;
      ping(Ip),
      ping(Ip, NProc - 1).
  
  init(Ip) -&gt;
      erlang:send_after(1000, self(), do_ping),
      {ok, Ip}.
  
  handle_call(_Request, _From, State) -&gt;
      {noreply, State}.
  
  handle_cast(stop, State) -&gt;
      io:format("~p is stopping~n", [State]),
      {stop, normal, State}.
  
  handle_info(do_ping, State) -&gt;
      io:format("pinging ~p~n", [State]),
      erlang:send_after(?PING_INTERVAL, self(), do_ping),
      {noreply, State};
  handle_info(Info, State) -&gt;
      io:format("Unknown message: ~p~n", [Info]),
      {noreply, State}.
  
  terminate(_Reason, State) -&gt;
      io:format("~p was terminated~n", [State]),
      ok.
  
  code_change(_OldVsn, State, _Extra) -&gt;
      {ok, State}.
  </code></pre>
  
  <p>It lacks of comments but I think it's very straightforward and familiar to any Erlang developer. I have few questions about this code:</p>
  
  <p>1) Is *erlang:send_after* in init a good solution? What is the best practise if I need process start doing the job immidiately it was spawned without triggering his functions from outside?</p>
  
  <p>2) Currently I initiate ping using <em>pinger:ping("127.0.0.1").</em> command. pinger module ask pinger_sup to start child process. After the process was started I want to stop it. What is the preferable way of doing it? Should I terminate it by sup or should I send him stop command? How should I store the process PID? Currently I use process dictionary but after implementing it I've realized that the dictionary actually doesn't belong to sup (it's a shell dictionary or any other stop_child caller). In case I use ETS and the sup was terminated would these dead process PIDs stay in ETS forever causing kind of memory leak?</p>
  
  <p>I appreciate any answers and code comments.</p>
  
  <p>Thanks!</p>