<div>
<div>
<span>That is an interesting point, and not something I'd considered to date<br>
</span>
<span><br>-- <br>Steve Strong<br>Sent with <a href="http://www.sparrowmailapp.com">Sparrow</a><br></span>
<p style="color: #a0a0a0;">On Thursday, June 2, 2011 at 4:10 PM, Frédéric Trottier-Hébert wrote:</p>
<blockquote type="cite" style="border-left-style:solid;border-width:1px;margin-left:0px;padding-left:10px;">
<span><div><div>There are disadvantages to *not* putting workers under the supervision tree, though. Namely, you'll be losing the ability to have the release handlers walk down the supervision trees to find which processes to suspend/update, and you'll then need to find a different way of doing things.<br><br>This is a serious point to consider if you ever plan on going the way of releases/appups if the workers you use are to be long-lived (you don't want them to be killed during a purge). I'm not saying you didn't know this, but I felt I should point it out for the sake of having the arguments clear on the mailing list. <br><br>--<br>Fred Hébert<br><a href="http://www.erlang-solutions.com">http://www.erlang-solutions.com</a><br><br><br>On 2011-06-02, at 05:53 AM, Mazen Harake wrote:<br><br><blockquote type="cite"><div>Steve,<br><br>I wouldn't say that you are wrong. I think that you are reasoning good<br>about not putting the gen_event module under a supervisor because<br>*that is what links are for*. Just because you have a supervisor<br>doesn't mean the you shove everything underneath there! If the<br>gen_server and the gen_event are truly linked (meaning: gen_server<br>doesn't act as a "supervisor" keeping track of its gen_event process<br>and restarts it all the time but rather that they really are linked<br>and they crash together) then your approach, in my opinion, is good.<br><br>There are great benefits in doing it in that way. Many will claim that<br>it is best practice to put *everything* under a supervisor but this is<br>simply not true. 90% of cases it *is* the best thing to do and many<br>times it is more about how you designed your application rather than<br>where to put the supervisors and their children but doing it the way<br>you did is not necessarily wrong.<br><br>The only problem I see with your approach is that you have registered<br>the gen_event process which clearly isn't useful (since only the<br>gen_server should know about it, after all, it started it). Other than<br>that, this approach is extremely helpful and a nice way to clean up<br>things after they die/shutdown (Again: assuming truly linked).<br><br>There is a big misconception in the community that everything<br>should/must look like the supervisor-tree model which shows how<br>gen_servers are put under supervisors and more supervisors under the<br>"top" supervisor but that is not enforced and the design principles<br>doesn't take many cases into account where this setup actually brings<br>more headache to the table than to just exit and clean up using linked<br>processes (because they do exist).<br><br>/M<br><br>On 1 June 2011 21:26, Steve Strong <<a href="mailto:steve@srstrong.com">steve@srstrong.com</a>> wrote:<br><blockquote type="cite"><div>Hi,<br><br>I've got some strange behaviour with gen_event within a supervision tree<br>which I don't fully understand. Consider the following supervisor<br>(completely standard, feel free to skip over):<br><snip><br>-module(sup).<br>-behaviour(supervisor).<br>-export([start_link/0, init/1]).<br>-define(SERVER, ?MODULE).<br>start_link() -><br> supervisor:start_link({local, ?SERVER}, ?MODULE, []).<br>init([]) -><br> Child1 = {child, {child, start_link, []}, permanent, 2000, worker,<br>[child]},<br> {ok, {{one_for_all, 1000, 3600}, [Child1]}}.<br></snip><br>and corresponding gen_server (interesting code in bold):<br><snip><br>-module(child).<br>-behaviour(gen_server).<br>-export([start_link/0, init/1, handle_call/3, handle_cast/2,<br>handle_info/2, terminate/2, code_change/3]).<br>start_link() -><br> gen_server:start_link({local, child}, child, [], []).<br>init([]) -><br> io:format("about to start gen_event~n"),<br> X = gen_event:start_link({local, my_gen_event}),<br> io:format("gen_event started with ~p~n", [X]),<br> {ok, _Pid} = X,<br> {ok, {}, 2000}.<br>handle_call(_Request, _From, State) -><br> {reply, ok, State}.<br>handle_cast(_Msg, State) -><br> {noreply, State}.<br>handle_info(_Info, State) -><br> io:format("about to crash...~n"),<br> 1 = 2,<br> {noreply, State}.<br>terminate(_Reason, _State) -><br> ok.<br>code_change(_OldVsn, State, _Extra) -><br> {ok, State}.<br></snip><br>If I run this from an erl shell like this:<br><snip><br>--> erl<br>Erlang R14B01 (erts-5.8.2) [source] [64-bit] [smp:2:2] [rq:2]<br>[async-threads:0] [hipe] [kernel-poll:false]<br>Eshell V5.8.2 (abort with ^G)<br>1> application:start(sasl), supervisor:start_link(sup, []).<br></snip><br><br>Then the supervisor & server start as expected. After 2 seconds the server<br>gets a timeout message and crashes itself; the supervisor obviously spots<br>this and restarts it. Within the init of the gen_server, it also does a<br>start_link on a gen_event process. By my understanding, whenever the<br>gen_server process exits, the gen_event will also be terminated.<br>However, every now and then I see the following output (a ton of sasl trace<br>omitted for clarity!):<br><snip><br>about to crash...<br>about to start gen_event<br>gen_event started with {error,{already_started,<0.79.0>}}<br>about to start gen_event<br>gen_event started with {error,{already_started,<0.79.0>}}<br>about to start gen_event<br></snip><br>What is happening is that the gen_server is crashing but on its restart the<br>gen_event process is still running - hence the gen_server fails in its init<br>and gets restarted again. Sometimes this loop clears after a few<br>iterations, other times it can continue until the parent supervisor gives<br>up, packs its bags and goes home.<br>So, my question is whether this is expected behaviour or not. I assume that<br>the termination of the linked child is happening asynchronously, and that<br>the supervisor is hence restarting its children before things have cleaned<br>up correctly - is that correct?<br>I can fix this particular scenario by trapping exits within the gen_server,<br>and then calling gen_event:stop within the terminate. Is this type of<br>processing necessary whenever a process is start_link'ed within a supervisor<br>tree, or is what I'm doing considered bad practice?<br>Thanks for your time,<br>Steve<br>--<br>Steve Strong, Director, id3as<br><a href="http://twitter.com/srstrong">twitter.com/srstrong</a><br><br><br>_______________________________________________<br>erlang-questions mailing list<br><a href="mailto:erlang-questions@erlang.org">erlang-questions@erlang.org</a><br><a href="http://erlang.org/mailman/listinfo/erlang-questions">http://erlang.org/mailman/listinfo/erlang-questions</a><br></div></blockquote>_______________________________________________<br>erlang-questions mailing list<br><a href="mailto:erlang-questions@erlang.org">erlang-questions@erlang.org</a><br><a href="http://erlang.org/mailman/listinfo/erlang-questions">http://erlang.org/mailman/listinfo/erlang-questions</a><br></div></blockquote></div></div></span>
</blockquote>
<div>
<br>
</div>
</div>
</div>