[erlang-questions] inets service startup

Serge Aleynikov serge@REDACTED
Wed Apr 11 15:26:13 CEST 2007

Ingela Anderton Andin wrote:
> Hi Serge!
> I do not know why that line was ever entered, and it was a bad idea not 
> to remove it altogether.
> The httpd_sup supervisor is a one_for_one supervisor which means that if 
> there is a problem
> with one child it should not affect the other children.  It is possible 
> to start several HTTP-servers
> and a configuration error in one of them should not have a bearing on 
> the others. Maybe the
> error could be reported differently to be more "user friendly".

I think it all depends on how critical that httpd service is in the 
process interdependency.  If you have an application that cannot live 
without an HTTP server, the current implementation doesn't allow for 
intercepting a service startup problem (say due to a bad configuration 
option in the HTTP config file) and reacting appropriately (perhaps by 
aborting the boot process).

The workaround I found was not to specify the HTTPD service in the inets 
environment options, but rather introduce an environment option 
{httpd_config_file, Filename::string()} in a custom application that 
would manage addition/removal of a child HTTPD process to/from the 
inets' supervisor.

While this solution works, this way of error handling doesn't seem 
appealing to me.  It looks that it would be nicer if INETS would offer 
some sort of customization of action of what to do on httpd service 
startup problems.

Below is the code describing this workaround.  One other issue with this 
approach is that if there are other httpd services started by inets 
though its own environment options, if we want to stop the httpd 
instance managed by our custom app, there doesn't seem to be an easy way 
of figuring out which httpd service to stop.  Perhaps returning httpd 
service's name {httpd_instance_sup, Addr, Port} by the 
httpd_sup:start_child/1 function would help.

%% start/2, stop/1 - application callbacks
start(_Type, StartArgs) ->
     case supervisor:start_link({local, ?MODULE}, ?MODULE, [StartArgs]) of
     {ok, Pid} ->
         % Start the HTTPD service for WebAdmin interface.  It will
         % hook itself to inets' supervisor
         case start_httpd() of
         {ok, _HttpdPid} ->
             {ok, Pid};
         {error, Reason} ->
             {error, Reason}
     {error, Error} ->
         {error, Error}

stop(_Reason) ->

start_httpd() ->
     case get_httpd_config_file() of
     {ok, ConfFile} ->
         case catch httpd_sup:start_child(ConfFile) of
         {ok, Pid} ->
             {ok, Pid};
         {error, Reason} ->
             {error, Reason};
         {'EXIT', {{badmatch, {error, Reason}}, _Stack}} ->
             % This is likely due to a badly formatted config file
             {error, Reason};
         {'EXIT', Reason} ->
             {error, Reason};
         Other ->
             {error, Other}
     {error, Reason} ->
         {error, Reason}

stop_httpd() ->
     case get_running_httpds() of
     [{Addr, Port}] ->
         httpd_sup:stop_child(Addr, Port),
     [] ->
     _ ->
         % Many HTTPD instances running.  Can't determine which one to stop.
         {error, cant_determine_httpd_instance}

get_httpd_config_file() ->
     case application:get_env(web, httpd_config_file) of
     {ok, ConfigFile} ->
         {ok, ConfigFile};
     undefined ->
         {error, "'httpd_config_file' parameter not defined for 'web' 

get_running_httpds() ->
     Children = supervisor:which_children(httpd_sup),
     [{Addr,Port} || 
{{httpd_instance_sup,Addr,Port},_Pid,supervisor,_Mod} <- Children].



> Regards Ingela -OTP Team
>>>> While accidentally entering wrong information in inets' server 
>>>> configuration file I got an error report stating that a child spec was 
>>>> not created.  As a result the corresponding service didn't get started.
>>>> Upon examining sources, I found the following code with 
>>>> exit({error,Reason}) commented out:
>>>> httpd_sup.erl:
>>>> ==============
>>>> child_spec([], Acc) ->
>>>>      Acc;
>>>> child_spec([{httpd, HttpdService} | Rest], Acc) ->
>>>>      NewHttpdService = mk_tuple_list(HttpdService),
>>>>      %%    Acc2 = child_spec2(NewHttpdService,Acc),
>>>>      NewAcc=
>>>>      case catch child_spec2(NewHttpdService) of
>>>>          {ok,Acc2} ->
>>>>          [Acc2|Acc];
>>>>          {error,Reason} ->
>>>>          error_msg("failed to create child spec for ~n~p~ndue to: ~p",
>>>>                [HttpdService,Reason]),
>>>> %       exit({error,Reason})
>>>>          Acc
>>>>      end,
>>>>      child_spec(Rest,NewAcc).
>>>> I was wondering what the authors had in mind by somewhat silently 
>>>> ignoring the critical error at startup.  Wouldn't it be proper to 
>>>> uncomment that line?
>>>> Serge
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://www.erlang.org/mailman/listinfo/erlang-questions

More information about the erlang-questions mailing list