<div>
<div>
<span>Hi,<br>
</span></div><div><span><br></span></div><div><span>I've got some strange behaviour with gen_event within a supervision tree which I don't fully understand. Consider the following supervisor (completely standard, feel free to skip over):</span></div><div><span><br></span></div><div><snip></div><div><br></div><div><span><div>-module(sup).</div><div>-behaviour(supervisor).</div><div>-export([start_link/0, init/1]).</div><div>-define(SERVER, ?MODULE).</div><div><br></div><div>start_link() -></div><div> supervisor:start_link({local, ?SERVER}, ?MODULE, []).</div><div><br></div><div>init([]) -></div><div> Child1 = {child, {child, start_link, []}, permanent, 2000, worker, [child]},</div><div> {ok, {{one_for_all, 1000, 3600}, [Child1]}}.</div><div><br></div><div></snip></div><div><br></div><div>and corresponding gen_server (interesting code in bold):</div></span></div><div><span><br></span></div><div><span><snip></span></div><div><span><br></span></div><div><span><div>-module(child).</div><div>-behaviour(gen_server).</div><div>-export([start_link/0, init/1, handle_call/3, handle_cast/2, </div><div><span class="Apple-tab-span" style="white-space:pre"> </span> handle_info/2, terminate/2, code_change/3]).</div><div><br></div><div>start_link() -></div><div> gen_server:start_link({local, child}, child, [], []).</div><div><br></div><div><b>init([]) -></b></div><div> <b> io:format("about to start gen_event~n"),</b></div><div><b> X = gen_event:start_link({local, my_gen_event}),</b></div><div><b> io:format("gen_event started with ~p~n", [X]),</b></div><div><b> {ok, _Pid} = X,</b></div><div><b><br></b></div><div><b> {ok, {}, 2000}.</b></div><div><br></div><div>handle_call(_Request, _From, State) -></div><div> {reply, ok, State}.</div><div><br></div><div>handle_cast(_Msg, State) -></div><div> {noreply, State}.</div><div><br></div><div><b>handle_info(_Info, State) -></b></div><div><b> io:format("about to crash...~n"),</b></div><div><b> 1 = 2,</b></div><div><b> {noreply, State}.</b></div><div><br></div><div>terminate(_Reason, _State) -></div><div> ok.</div><div><br></div><div>code_change(_OldVsn, State, _Extra) -></div><div> {ok, State}.</div><div><br></div><div></snip></div><div><br></div><div>If I run this from an erl shell like this:</div><div><br></div><div><snip></div><div><br></div><div><div>--> erl</div><div>Erlang R14B01 (erts-5.8.2) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]</div><div><br></div><div>Eshell V5.8.2 (abort with ^G)</div><div>1> application:start(sasl), supervisor:start_link(sup, []).</div></div><div><br></div></span></div><div>
<span></snip><br><div><br></div><div>Then the supervisor & server start as expected. After 2 seconds the server gets a timeout message and crashes itself; the supervisor obviously spots this and restarts it. Within the init of the gen_server, it also does a start_link on a gen_event process. By my understanding, whenever the gen_server process exits, the gen_event will also be terminated.</div><div><br></div><div>However, every now and then I see the following output (a ton of sasl trace omitted for clarity!):</div><div><br></div><div><snip></div><div><br></div><div><div>about to crash...</div><div>about to start gen_event</div><div>gen_event started with {error,{already_started,<0.79.0>}}</div><div>about to start gen_event</div><div>gen_event started with {error,{already_started,<0.79.0>}}</div><div>about to start gen_event</div></div><div><br></div><div></snip></div><div><br></div><div>What is happening is that the gen_server is crashing but on its restart the gen_event process is still running - hence the gen_server fails in its init and gets restarted again. Sometimes this loop clears after a few iterations, other times it can continue until the parent supervisor gives up, packs its bags and goes home.</div><div><br></div><div>So, my question is whether this is expected behaviour or not. I assume that the termination of the linked child is happening asynchronously, and that the supervisor is hence restarting its children before things have cleaned up correctly - is that correct?</div><div><br></div><div>I can fix this particular scenario by trapping exits within the gen_server, and then calling gen_event:stop within the terminate. Is this type of processing necessary whenever a process is start_link'ed within a supervisor tree, or is what I'm doing considered bad practice?</div><div><br></div><div>Thanks for your time,</div><div><br></div><div>Steve</div><div><br></div><div>-- </div>Steve Strong, Director, id3as<br><div>twitter.com/srstrong</div><br></span></div><div><span><br></span></div><div>
</div>
</div>