<br><div class="gmail_quote">On Thu, Apr 25, 2013 at 11:19 AM, Bengt Kleberg <span dir="ltr"><<a href="mailto:bengt.kleberg@ericsson.com" target="_blank">bengt.kleberg@ericsson.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<br>
Under what circumstances will gen_server:start_link/3 return {error,<br>
Reason}?<br></blockquote><div><br>You are right, there is an inconsistency in the documentation.<br>So let's have a look at the code of gen_server:start_link/3.<br><br>In gen_server.erl<br>------------------------<br>

start_link(Mod, Args, Options) -><br>    gen:start(?MODULE, link, Mod, Args, Options).<br><br>In gen.erl<br>--------------<br>start(GenMod, LinkP, Mod, Args, Options) -><br>    do_spawn(GenMod, LinkP, Mod, Args, Options).<br>

<br>%% We only need this clause as LinkP =:= link in our case<br>do_spawn(GenMod, link, Mod, Args, Options) -><br>    Time = timeout(Options),<br>    proc_lib:start_link(?MODULE, init_it,<br>                              [GenMod, self(), self(), Mod, Args, Options],<br>

                              Time,<br>                              spawn_opts(Options));<br><br>init_it(GenMod, Starter, Parent, Mod, Args, Options) -><br>    init_it2(GenMod, Starter, Parent, self(), Mod, Args, Options).<br>

<br>init_it2(GenMod, Starter, Parent, Name, Mod, Args, Options) -><br>    %% So in our case will call gen_server:init_it/6 where Parent will be the a PID<br>    GenMod:init_it(Starter, Parent, Name, Mod, Args, Options).<br>

<br>In gen_server.erl<br>------------------------<br>init_it(Starter, Parent, Name0, Mod, Args, Options) -><br>    Name = name(Name0),<br>    Debug = debug_options(Name, Options),<br>    %% The actual call of our module's init function<br>

    case catch Mod:init(Args) of<br>    {ok, State} -><br>        proc_lib:init_ack(Starter, {ok, self()}),<br>        loop(Parent, Name, State, Mod, infinity, Debug);<br>    {ok, State, Timeout} -><br>        proc_lib:init_ack(Starter, {ok, self()}),<br>

        loop(Parent, Name, State, Mod, Timeout, Debug);<br>    {stop, Reason} -><br>        unregister_name(Name0),<br>        proc_lib:init_ack(Starter, {error, Reason}),<br>        exit(Reason);<br>    ignore -><br>

        unregister_name(Name0),<br>        proc_lib:init_ack(Starter, ignore),<br>        exit(normal);<br>    {'EXIT', Reason} -><br>        unregister_name(Name0),<br>        proc_lib:init_ack(Starter, {error, Reason}),<br>

        exit(Reason);<br>    Else -><br>        Error = {bad_return_value, Else},<br>        proc_lib:init_ack(Starter, {error, Error}),<br>        exit(Error)<br>    end.<br><br>So we see that if our module's init function returns {stop, Reason} or exits with Reason then proc_lib:init_ack(Starter, {error, Reason}) will make proc_lib:start_link return {error, Reason}, but then exit(Reason) will actually cause the spawned server process to crash and subsequently the process that called gen_server:start_link.<br>

The behaviour you notice is thus completely justified and the only way that the behaviour the documentation describes is accurate is when your process traps exits and not allows exit(Reason) to crash it.<br><br>Sorry for the long post! I hope this cleared things up!<br>

<br>Aggelos<br></div></div>