continued init (RE: OTP or not to OTP)

Ulf Wiger <>
Mon Mar 3 14:18:24 CET 2003


On Mon, 3 Mar 2003, Sean Hinde wrote:

>The main tcp/ip server model we use in our systems is made
>of 2 gen_servers. The only difference to the 'pure' erlang
>version is that the startup of the accepting gen_server
>process is made slightly more complex. The init function
>sends a message to itself to start up the accept call in
>the main callbacks otherwise the starting process would
>hang.


Some people will probably want to strangle me for revealing
this "secret", but you can actually do this:

start_link() ->
   gen_server:start_link({local,myserver},?MODULE,self(),[]).

init(Parent) ->
   ...,
   proc_lib:init_ack(Parent, {ok,self()}),
   State = ...,
   {ok, State}.

The supervisor will quietly consume the second 'ack'
message.

It is frowned upon, but accepted for now. A better solution
will eventually appear, so it will remain undocumented.
Therefore, use it at your own peril, and only if you can
promise not to blame me when it breaks. (:

The place where this is preferrable to self() ! continue, is
for example during process restarts, when clients are active
and may succeed in calling the server before you have time
to send to yourself. It is very difficult to close this hole
entirely, and the above "hack" eliminates the problem
(introducing a less serious "double ack" problem, which can
be handled in supervisor.erl)

The Better Solution will probably be something along the
lines of init/1 returning {continue, fun()}, or something.
Stay tuned (or take a look at my attached suggestion for a
patch -- my way of trying to appease the OTP Gods after
having promoted dirty hacks to the public... ;-)

/Uffe
-- 
Ulf Wiger, Senior Specialist,
   / / /   Architecture & Design of Carrier-Class Software
  / / /    Strategic Product & System Management
 / / /     Ericsson AB, Connectivity and Control Nodes


-------------- next part --------------
382,384d381
< 	{continue, F} when function(F) ->
< 	    proc_lib:init_ack(Starter, {ok, self()}),
< 	    continued_init(F, Parent, Name, Mod, Debug);
400,409d396
< continued_init(F, Parent, Name, Mod, Debug) ->
<     case catch F() of
< 	{'EXIT', Reason} ->
< 	    terminate(Reason, Name, continued_init, Mod, undefined, []);
< 	{ok, State} ->
< 	    loop(Parent, Name, State, Mod, infinity, Debug);
< 	{ok, State, Timeout} ->
< 	    loop(Parent, Name, State, Mod, Timeout, Debug)
<     end.
< 
591,595d577
<     error_msg(Name, Msg, State, Reason),
<     sys:print_log(Debug),
<     ok.
< 
< error_msg(Name, continued_init, undefined, Reason) ->
597,601d578
<            "** during continued_init.~n"
<            "** Reason for termination == ~n** ~p~n",
< 	   [Name, Reason]);
< error_msg(Name, Msg, State, Reason) ->
<     format("** Generic server ~p terminating \n"
605c582,584
< 	   [Name, Msg, State, Reason]).
---
> 	   [Name, Msg, State, Reason]),
>     sys:print_log(Debug),
>     ok.
607d585
< 


More information about the erlang-questions mailing list