I am trying to write a supervisor for a process that I have made. I have investigated this for some time to no avail so hopefully someone can help.
I have certain restrictions on the interface I have to use as this is for an assignment, so I am aware of the examples using Lists and also more elaborate OTP examples on the Erlang site, however these are not suitable. I have provided and example abstracted from my application to demonstrate the issue.
I am trying to restart an arbitrary worker when it is exited for none normal reasons. The worker process is simply:
-module(my_mod).
-export([start/1, init/1]).
start(Pid)->
{ok, spawn_link(?MODULE, init, [Pid])}.
init(Pid) ->
register(Pid, self()),
io:format("Started ~p~n",[Pid]),
loop().
loop() ->
receive stop -> exit(byebye) end.
In the supervisor I am using ETS tabs to keep track of the workers and restart them, the supervisor is as such:
-module(my_sup).
-export([start_link/0, init/1, add_item/1, remove_item/1]).
start_link() ->
spawn(?MODULE, init, [self()]).
init(Pid) ->
process_flag(trap_exit, true),
register(?MODULE, Pid),
ets:new(?MODULE, [set, named_table, public]),
loop().
add_item(Pid) ->
ets:insert(?MODULE, {Pid}),
my_mod:start(Pid),
{ok, Pid}.
remove_item(Pid) ->
ets:delete(?MODULE, [Pid]).
loop() ->
io:format("Looping ~n"),
receive
{'EXIT', Pid, _Reason} ->
remove_item(Pid),
add_item(Pid)
end.
So I believe I am doing somethings right here, my_mod is linked back to the supervisor so that it is notified of the exit signal, the supervisor has the trap_exit set so that the supervisor has to opportunity to handle the signal. However I am finding that I just get a ** exception exit: stop thrown and I am not sure why this is?
My test case is the following:
1> c(my_sup), c(my_mod), my_sup:start_link().
Looping
<0.42.0>
2> my_sup:add_item(a).
Started a
{ok,a}
3> a ! stop .
** exception exit: byebye
Can anyone point me in the right direction?
In your shell your
add_item/1
call occurs within the shell process, not within the supervisor process, which means the supervisor is not linked to the newly-added process, but rather your shell is. Inadd_item/1
you should instead send a message into the supervisor process to tell it to launch a new worker, and change your supervisor loop to handle that new message and launch the worker from there.