aboutsummaryrefslogtreecommitdiffstats
path: root/lib/inets/src
diff options
context:
space:
mode:
authorIngela Anderton Andin <[email protected]>2013-12-17 09:14:56 +0100
committerIngela Anderton Andin <[email protected]>2014-02-05 10:32:28 +0100
commite848019d1308e4dc20249ef7368ba1bdc01a0d9b (patch)
treef06e21fa5ed0a5767904b0e8cb6227ec77bec74f /lib/inets/src
parent5b40274acb3355d23e65ef59def92e92f89c72e2 (diff)
downloadotp-e848019d1308e4dc20249ef7368ba1bdc01a0d9b.tar.gz
otp-e848019d1308e4dc20249ef7368ba1bdc01a0d9b.tar.bz2
otp-e848019d1308e4dc20249ef7368ba1bdc01a0d9b.zip
inets: Mend broken max_clients check
Conflicts: lib/inets/src/http_server/httpd_manager.erl Conflicts: lib/inets/test/inets_sup_SUITE.erl
Diffstat (limited to 'lib/inets/src')
-rw-r--r--lib/inets/src/http_server/Makefile3
-rw-r--r--lib/inets/src/http_server/httpd_acceptor.erl112
-rw-r--r--lib/inets/src/http_server/httpd_acceptor_sup.erl84
-rw-r--r--lib/inets/src/http_server/httpd_connection_sup.erl65
-rw-r--r--lib/inets/src/http_server/httpd_instance_sup.erl30
-rw-r--r--lib/inets/src/http_server/httpd_manager.erl565
-rw-r--r--lib/inets/src/http_server/httpd_request_handler.erl95
-rw-r--r--lib/inets/src/inets_app/inets.app.src3
8 files changed, 365 insertions, 592 deletions
diff --git a/lib/inets/src/http_server/Makefile b/lib/inets/src/http_server/Makefile
index 67555d5f1c..ae75bc2b54 100644
--- a/lib/inets/src/http_server/Makefile
+++ b/lib/inets/src/http_server/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2012. All Rights Reserved.
+# Copyright Ericsson AB 2005-2014. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -43,6 +43,7 @@ MODULES = \
httpd \
httpd_acceptor \
httpd_acceptor_sup \
+ httpd_connection_sup\
httpd_cgi \
httpd_conf \
httpd_example \
diff --git a/lib/inets/src/http_server/httpd_acceptor.erl b/lib/inets/src/http_server/httpd_acceptor.erl
index e79dfce0cb..73ed5c0769 100644
--- a/lib/inets/src/http_server/httpd_acceptor.erl
+++ b/lib/inets/src/http_server/httpd_acceptor.erl
@@ -21,13 +21,13 @@
-include("httpd.hrl").
-include("httpd_internal.hrl").
--include("inets_internal.hrl").
+%%-include("inets_internal.hrl").
%% Internal application API
--export([start_link/6, start_link/7]).
+-export([start_link/7, start_link/8]).
%% Other exports (for spawn's etc.)
--export([acceptor_init/7, acceptor_init/8, acceptor_loop/6]).
+-export([acceptor_init/8, acceptor_init/9, acceptor_loop/8]).
%%
%% External API
@@ -36,51 +36,52 @@
%% start_link
start_link(Manager, SocketType, Addr, Port, IpFamily, ConfigDb, AcceptTimeout) ->
- ?hdrd("start link",
- [{manager, Manager},
- {socket_type, SocketType},
- {address, Addr},
- {port, Port},
- {timeout, AcceptTimeout}]),
+ %% ?hdrd("start link",
+ %% [{manager, Manager},
+ %% {socket_type, SocketType},
+ %% {address, Addr},
+ %% {port, Port},
+ %% {timeout, AcceptTimeout}]),
Args = [self(), Manager, SocketType, Addr, Port, IpFamily, ConfigDb, AcceptTimeout],
proc_lib:start_link(?MODULE, acceptor_init, Args).
-start_link(Manager, SocketType, ListenSocket, IpFamily, ConfigDb, AcceptTimeout) ->
- ?hdrd("start link",
- [{manager, Manager},
- {socket_type, SocketType},
- {listen_socket, ListenSocket},
- {timeout, AcceptTimeout}]),
- Args = [self(), Manager, SocketType, ListenSocket, IpFamily,
+start_link(Manager, SocketType, Addr, Port, ListenSocket, IpFamily, ConfigDb, AcceptTimeout) ->
+ %% ?hdrd("start link",
+ %% [{manager, Manager},
+ %% {socket_type, SocketType},
+ %% {listen_socket, ListenSocket},
+ %% {timeout, AcceptTimeout}]),
+ Args = [self(), Manager, SocketType, Addr, Port, ListenSocket, IpFamily,
ConfigDb, AcceptTimeout],
proc_lib:start_link(?MODULE, acceptor_init, Args).
-acceptor_init(Parent, Manager, SocketType, {ListenOwner, ListenSocket}, IpFamily,
+acceptor_init(Parent, Manager, SocketType, Addr, Port, {ListenOwner, ListenSocket}, IpFamily,
ConfigDb, AcceptTimeout) ->
- ?hdrd("acceptor init",
- [{parent, Parent},
- {manager, Manager},
- {socket_type, SocketType},
- {listen_owner, ListenOwner},
- {listen_socket, ListenSocket},
- {timeout, AcceptTimeout}]),
+ %% ?hdrd("acceptor init",
+ %% [{parent, Parent},
+ %% {manager, Manager},
+ %% {socket_type, SocketType},
+ %% {listen_owner, ListenOwner},
+ %% {listen_socket, ListenSocket},
+ %% {timeout, AcceptTimeout}]),
link(ListenOwner),
proc_lib:init_ack(Parent, {ok, self()}),
- acceptor_loop(Manager, SocketType, ListenSocket, IpFamily, ConfigDb, AcceptTimeout).
+ acceptor_loop(Manager, SocketType, Addr, Port,
+ ListenSocket, IpFamily, ConfigDb, AcceptTimeout).
acceptor_init(Parent, Manager, SocketType, Addr, Port, IpFamily,
ConfigDb, AcceptTimeout) ->
- ?hdrd("acceptor init",
- [{parent, Parent},
- {manager, Manager},
- {socket_type, SocketType},
- {address, Addr},
- {port, Port},
- {timeout, AcceptTimeout}]),
+ %% ?hdrd("acceptor init",
+ %% [{parent, Parent},
+ %% {manager, Manager},
+ %% {socket_type, SocketType},
+ %% {address, Addr},
+ %% {port, Port},
+ %% {timeout, AcceptTimeout}]),
case (catch do_init(SocketType, Addr, Port, IpFamily)) of
{ok, ListenSocket} ->
proc_lib:init_ack(Parent, {ok, self()}),
- acceptor_loop(Manager, SocketType,
+ acceptor_loop(Manager, SocketType, Addr, Port,
ListenSocket, IpFamily,ConfigDb, AcceptTimeout);
Error ->
proc_lib:init_ack(Parent, Error),
@@ -88,67 +89,68 @@ acceptor_init(Parent, Manager, SocketType, Addr, Port, IpFamily,
end.
do_init(SocketType, Addr, Port, IpFamily) ->
- ?hdrt("do init", []),
+ %% ?hdrt("do init", []),
do_socket_start(SocketType),
ListenSocket = do_socket_listen(SocketType, Addr, Port, IpFamily),
{ok, ListenSocket}.
do_socket_start(SocketType) ->
- ?hdrt("do socket start", []),
+ %% ?hdrt("do socket start", []),
case http_transport:start(SocketType) of
ok ->
ok;
{error, Reason} ->
- ?hdrv("failed starting transport", [{reason, Reason}]),
+ %% ?hdrv("failed starting transport", [{reason, Reason}]),
throw({error, {socket_start_failed, Reason}})
end.
do_socket_listen(SocketType, Addr, Port, IpFamily) ->
- ?hdrt("do socket listen", []),
+ %% ?hdrt("do socket listen", []),
case http_transport:listen(SocketType, Addr, Port, IpFamily) of
{ok, ListenSocket} ->
ListenSocket;
{error, Reason} ->
- ?hdrv("listen failed", [{reason, Reason},
- {socket_type, SocketType},
- {addr, Addr},
- {port, Port}]),
+ %% ?hdrv("listen failed", [{reason, Reason},
+ %% {socket_type, SocketType},
+ %% {addr, Addr},
+ %% {port, Port}]),
throw({error, {listen, Reason}})
end.
%% acceptor
-acceptor_loop(Manager, SocketType, ListenSocket, IpFamily, ConfigDb, AcceptTimeout) ->
- ?hdrd("awaiting accept",
- [{manager, Manager},
- {socket_type, SocketType},
- {listen_socket, ListenSocket},
- {timeout, AcceptTimeout}]),
+acceptor_loop(Manager, SocketType, Addr, Port, ListenSocket, IpFamily, ConfigDb, AcceptTimeout) ->
+ %% ?hdrd("awaiting accept",
+ %% [{manager, Manager},
+ %% {socket_type, SocketType},
+ %% {listen_socket, ListenSocket},
+ %% {timeout, AcceptTimeout}]),
case (catch http_transport:accept(SocketType, ListenSocket, 50000)) of
{ok, Socket} ->
- ?hdrv("accepted", [{socket, Socket}]),
- handle_connection(Manager, ConfigDb, AcceptTimeout,
+ %% ?hdrv("accepted", [{socket, Socket}]),
+ handle_connection(Addr, Port, Manager, ConfigDb, AcceptTimeout,
SocketType, Socket),
- ?MODULE:acceptor_loop(Manager, SocketType,
+ ?MODULE:acceptor_loop(Manager, SocketType, Addr, Port,
ListenSocket, IpFamily, ConfigDb,AcceptTimeout);
{error, Reason} ->
- ?hdri("accept failed", [{reason, Reason}]),
+ %% ?hdri("accept failed", [{reason, Reason}]),
handle_error(Reason, ConfigDb),
- ?MODULE:acceptor_loop(Manager, SocketType, ListenSocket,
+ ?MODULE:acceptor_loop(Manager, SocketType, Addr, Port, ListenSocket,
IpFamily, ConfigDb, AcceptTimeout);
{'EXIT', Reason} ->
- ?hdri("accept exited", [{reason, Reason}]),
+ %% ?hdri("accept exited", [{reason, Reason}]),
ReasonString =
lists:flatten(io_lib:format("Accept exit: ~p", [Reason])),
accept_failed(ConfigDb, ReasonString)
end.
-handle_connection(Manager, ConfigDb, AcceptTimeout, SocketType, Socket) ->
- {ok, Pid} = httpd_request_handler:start(Manager, ConfigDb, AcceptTimeout),
+handle_connection(Address, Port, Manager, ConfigDb, AcceptTimeout, SocketType, Socket) ->
+ Sup = httpd_connection_sup:connection_sup(Address, Port),
+ {ok, Pid} = httpd_connection_sup:start_child(Sup, [Manager, ConfigDb, AcceptTimeout]),
http_transport:controlling_process(SocketType, Socket, Pid),
httpd_request_handler:socket_ownership_transfered(Pid, SocketType, Socket).
diff --git a/lib/inets/src/http_server/httpd_acceptor_sup.erl b/lib/inets/src/http_server/httpd_acceptor_sup.erl
index 0cae8dbe47..9173a6d1b0 100644
--- a/lib/inets/src/http_server/httpd_acceptor_sup.erl
+++ b/lib/inets/src/http_server/httpd_acceptor_sup.erl
@@ -27,7 +27,8 @@
-behaviour(supervisor).
%% API
--export([start_link/2, start_acceptor/6, start_acceptor/7, stop_acceptor/2]).
+-export([start_link/1]).
+%%, start_acceptor/6, start_acceptor/7, stop_acceptor/2]).
%% Supervisor callback
-export([init/1]).
@@ -35,63 +36,48 @@
%%%=========================================================================
%%% API
%%%=========================================================================
-start_link(Addr, Port) ->
+start_link([Addr, Port| _] = Args) ->
SupName = make_name(Addr, Port),
- supervisor:start_link({local, SupName}, ?MODULE, []).
-
-%%----------------------------------------------------------------------
-%% Function: [start|stop]_acceptor/5
-%% Description: Starts/stops an [auth | security] worker (child) process
-%%----------------------------------------------------------------------
-start_acceptor(SocketType, Addr, Port, IpFamily, ConfigDb, AcceptTimeout) ->
- start_worker(httpd_acceptor, SocketType, Addr, Port, IpFamily,
- ConfigDb, AcceptTimeout, self(), []).
-start_acceptor(SocketType, Addr, Port, IpFamily, ConfigDb, AcceptTimeout, ListenSocket) ->
- start_worker(httpd_acceptor, SocketType, Addr, Port, IpFamily,
- ConfigDb, AcceptTimeout, ListenSocket, self(), []).
-
-
-stop_acceptor(Addr, Port) ->
- stop_worker(httpd_acceptor, Addr, Port).
+ supervisor:start_link({local, SupName}, ?MODULE, [Args]).
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
-init(_) ->
- Flags = {one_for_one, 500, 100},
- Workers = [],
- {ok, {Flags, Workers}}.
+init([Args]) ->
+ RestartStrategy = one_for_one,
+ MaxR = 10,
+ MaxT = 3600,
+ Children = [child_spec(Args)],
+ {ok, {{RestartStrategy, MaxR, MaxT}, Children}}.
%%%=========================================================================
%%% Internal functions
%%%=========================================================================
+child_spec([Address, Port, ConfigList, AcceptTimeout, ListenInfo]) ->
+ Name = id(Address, Port),
+ Manager = httpd_util:make_name("httpd", Address, Port),
+ SockType = proplists:get_value(socket_type, ConfigList, ip_comm),
+ IpFamily = proplists:get_value(ipfamily, ConfigList, inet),
+ StartFunc = case ListenInfo of
+ undefined ->
+ {httpd_acceptor, start_link, [Manager, SockType, Address, Port, IpFamily,
+ httpd_util:make_name("httpd_conf", Address, Port),
+ AcceptTimeout]};
+ _ ->
+ {httpd_acceptor, start_link, [Manager, SockType, Address, Port, ListenInfo,
+ IpFamily,
+ httpd_util:make_name("httpd_conf", Address, Port),
+ AcceptTimeout]}
+ end,
+ Restart = transient,
+ Shutdown = brutal_kill,
+ Modules = [httpd_acceptor],
+ Type = worker,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
-make_name(Addr,Port) ->
- httpd_util:make_name("httpd_acc_sup", Addr, Port).
+id(Address, Port) ->
+ {httpd_acceptor_sup, Address, Port}.
-start_worker(M, SocketType, Addr, Port, IpFamily, ConfigDB, AcceptTimeout, Manager, Modules) ->
- SupName = make_name(Addr, Port),
- Args = [Manager, SocketType, Addr, Port, IpFamily, ConfigDB, AcceptTimeout],
- Spec = {{M, Addr, Port},
- {M, start_link, Args},
- permanent, timer:seconds(1), worker, [M] ++ Modules},
- supervisor:start_child(SupName, Spec).
-
-start_worker(M, SocketType, Addr, Port, IpFamily, ConfigDB, AcceptTimeout, ListenSocket,
- Manager, Modules) ->
- SupName = make_name(Addr, Port),
- Args = [Manager, SocketType, ListenSocket, IpFamily, ConfigDB, AcceptTimeout],
- Spec = {{M, Addr, Port},
- {M, start_link, Args},
- permanent, timer:seconds(1), worker, [M] ++ Modules},
- supervisor:start_child(SupName, Spec).
+make_name(Addr,Port) ->
+ httpd_util:make_name("httpd_acceptor_sup", Addr, Port).
-stop_worker(M, Addr, Port) ->
- SupName = make_name(Addr, Port),
- Name = {M, Addr, Port},
- case supervisor:terminate_child(SupName, Name) of
- ok ->
- supervisor:delete_child(SupName, Name);
- Error ->
- Error
- end.
diff --git a/lib/inets/src/http_server/httpd_connection_sup.erl b/lib/inets/src/http_server/httpd_connection_sup.erl
new file mode 100644
index 0000000000..eac5e1b550
--- /dev/null
+++ b/lib/inets/src/http_server/httpd_connection_sup.erl
@@ -0,0 +1,65 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2014. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Ssh connection supervisor.
+%%----------------------------------------------------------------------
+
+-module(httpd_connection_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/1]).
+-export([start_child/2, connection_sup/2]).
+
+%% Supervisor callback
+-export([init/1]).
+
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+start_link(Args) ->
+ supervisor:start_link(?MODULE, [Args]).
+
+start_child(Sup, Args) ->
+ supervisor:start_child(Sup, Args).
+
+connection_sup(Addr, Port) ->
+ httpd_util:make_name("httpd_connection_sup", Addr, Port).
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+init([[Addr, Port]]) ->
+ RegName = connection_sup(Addr, Port),
+ register(RegName, self()),
+ RestartStrategy = simple_one_for_one,
+ MaxR = 0,
+ MaxT = 3600,
+
+ Name = undefined, % As simple_one_for_one is used.
+ StartFunc = {httpd_request_handler, start_link, []},
+ Restart = temporary, % E.g. should not be restarted
+ Shutdown = 4000,
+ Modules = [httpd_request_handler],
+ Type = worker,
+
+ ChildSpec = {Name, StartFunc, Restart, Shutdown, Type, Modules},
+ {ok, {{RestartStrategy, MaxR, MaxT}, [ChildSpec]}}.
diff --git a/lib/inets/src/http_server/httpd_instance_sup.erl b/lib/inets/src/http_server/httpd_instance_sup.erl
index baa60d318c..383a55f594 100644
--- a/lib/inets/src/http_server/httpd_instance_sup.erl
+++ b/lib/inets/src/http_server/httpd_instance_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2014. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -100,7 +100,9 @@ start_link(ConfigFile, AcceptTimeout, ListenInfo, Debug) ->
init([ConfigFile, ConfigList, AcceptTimeout, Debug, Address, Port]) ->
httpd_util:enable_debug(Debug),
Flags = {one_for_one, 0, 1},
- Children = [sup_spec(httpd_acceptor_sup, Address, Port),
+ Children = [httpd_connection_sup_spec(Address, Port),
+ httpd_acceptor_sup_spec(Address, Port, ConfigList, AcceptTimeout,
+ undefined),
sup_spec(httpd_misc_sup, Address, Port),
worker_spec(httpd_manager, Address, Port,
ConfigFile, ConfigList,AcceptTimeout)],
@@ -108,7 +110,9 @@ init([ConfigFile, ConfigList, AcceptTimeout, Debug, Address, Port]) ->
init([ConfigFile, ConfigList, AcceptTimeout, Debug, Address, Port, ListenInfo]) ->
httpd_util:enable_debug(Debug),
Flags = {one_for_one, 0, 1},
- Children = [sup_spec(httpd_acceptor_sup, Address, Port),
+ Children = [httpd_connection_sup_spec(Address, Port),
+ httpd_acceptor_sup_spec(Address, Port, ConfigList, AcceptTimeout,
+ ListenInfo),
sup_spec(httpd_misc_sup, Address, Port),
worker_spec(httpd_manager, Address, Port, ListenInfo,
ConfigFile, ConfigList, AcceptTimeout)],
@@ -118,6 +122,24 @@ init([ConfigFile, ConfigList, AcceptTimeout, Debug, Address, Port, ListenInfo])
%%%=========================================================================
%%% Internal functions
%%%=========================================================================
+httpd_connection_sup_spec(Address, Port) ->
+ Name = {httpd_connection_sup, Address, Port},
+ StartFunc = {httpd_connection_sup, start_link, [[Address, Port]]},
+ Restart = permanent,
+ Shutdown = 5000,
+ Modules = [httpd_connection_sup],
+ Type = supervisor,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
+httpd_acceptor_sup_spec(Address, Port, ConfigList, AcceptTimeout, ListenInfo) ->
+ Name = {httpd_acceptor_sup, Address, Port},
+ StartFunc = {httpd_acceptor_sup, start_link, [[Address, Port, ConfigList, AcceptTimeout, ListenInfo]]},
+ Restart = permanent,
+ Shutdown = infinity,
+ Modules = [httpd_acceptor_sup],
+ Type = supervisor,
+ {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+
sup_spec(SupModule, Address, Port) ->
Name = {SupModule, Address, Port},
StartFunc = {SupModule, start_link, [Address, Port]},
@@ -167,5 +189,3 @@ file_2_config(ConfigFile) ->
Error ->
Error
end.
-
-
diff --git a/lib/inets/src/http_server/httpd_manager.erl b/lib/inets/src/http_server/httpd_manager.erl
index f6ae0d0933..82dbb2a149 100644
--- a/lib/inets/src/http_server/httpd_manager.erl
+++ b/lib/inets/src/http_server/httpd_manager.erl
@@ -25,9 +25,11 @@
-behaviour(gen_server).
%% Application internal API
--export([start/2, start_link/2, start_link/3, start_link/4, stop/1, reload/2]).
--export([new_connection/1, done_connection/1]).
+-export([start/2, start_link/2, start_link/3, start_link/4,
+ stop/1, reload/2]).
+-export([new_connection/1]).
-export([config_match/2, config_match/3]).
+-export([block/2, block/3, unblock/1]).
%% gen_server exports
-export([init/1,
@@ -35,26 +37,19 @@
terminate/2,
code_change/3]).
-
-%% Management exports
--export([block/2, block/3, unblock/1]).
-
-record(state,{socket_type = ip_comm,
config_file,
config_db = null,
- connections, %% Current request handlers
+ connection_sup,
admin_state = unblocked,
blocker_ref = undefined,
- blocking_tmr = undefined,
+ blocking_from = undefined,
+ shutdown_poller = undefined,
status = []}).
+%%%--------------------------------------------------------------------
+%%% Application internal API
+%%%--------------------------------------------------------------------
-
-%%TODO: Clean up this module!
-
-
-%%
-%% External API
-%%
%% Deprecated
start(ConfigFile, ConfigList) ->
Port = proplists:get_value(port,ConfigList,80),
@@ -73,7 +68,8 @@ start_link(ConfigFile, ConfigList, AcceptTimeout) ->
Name = make_name(Addr, Port),
gen_server:start_link({local, Name},?MODULE,
- [ConfigFile, ConfigList, AcceptTimeout, Addr, Port],[]).
+ [ConfigFile, ConfigList,
+ AcceptTimeout, Addr, Port],[]).
start_link(ConfigFile, ConfigList, AcceptTimeout, ListenSocket) ->
Port = proplists:get_value(port, ConfigList, 80),
@@ -83,81 +79,33 @@ start_link(ConfigFile, ConfigList, AcceptTimeout, ListenSocket) ->
gen_server:start_link({local, Name},?MODULE,
[ConfigFile, ConfigList, AcceptTimeout, Addr,
Port, ListenSocket],[]).
-
stop(ServerRef) ->
call(ServerRef, stop).
reload(ServerRef, Conf) ->
call(ServerRef, {reload, Conf}).
-
-%%%----------------------------------------------------------------
-
-block(ServerRef, disturbing) ->
- call(ServerRef,block);
-
-block(ServerRef, non_disturbing) ->
- do_block(ServerRef, non_disturbing, infinity).
+block(ServerRef, Method) ->
+ block(ServerRef, Method, infinity).
block(ServerRef, Method, Timeout) ->
- do_block(ServerRef, Method, Timeout).
-
-
-%% The reason for not using call here, is that the manager cannot
-%% _wait_ for completion of the requests. It must be able to do
-%% do other things at the same time as the blocking goes on.
-do_block(ServerRef, Method, infinity) ->
- Ref = make_ref(),
- cast(ServerRef, {block, Method, infinity, self(), Ref}),
- receive
- {block_reply, Reply, Ref} ->
- Reply
- end;
-do_block(ServerRef,Method,Timeout) when Timeout > 0 ->
- Ref = make_ref(),
- cast(ServerRef,{block,Method,Timeout,self(),Ref}),
- receive
- {block_reply,Reply,Ref} ->
- Reply
- end.
-
-
-%%%----------------------------------------------------------------
-
-%% unblock
+ call(ServerRef, {block, self(), Method, Timeout}).
unblock(ServerRef) ->
- call(ServerRef,unblock).
-
-
-%% Internal API
-%%
-
-
-%% new_connection
+ call(ServerRef,{unblock, self()}).
new_connection(Manager) ->
call(Manager, {new_connection, self()}).
-%% done
-
-done_connection(Manager) ->
- cast(Manager, {done_connection, self()}).
-
-
config_match(Port, Pattern) ->
config_match(undefined,Port,Pattern).
config_match(Addr, Port, Pattern) ->
Name = httpd_util:make_name("httpd",Addr,Port),
call(whereis(Name), {config_match, Pattern}).
-
-%%
-%% Server call-back functions
-%%
-
-%% init
-
+%%%--------------------------------------------------------------------
+%%% gen_server callbacks functions
+%%%--------------------------------------------------------------------
init([ConfigFile, ConfigList, AcceptTimeout, Addr, Port]) ->
process_flag(trap_exit, true),
case (catch do_init(ConfigFile, ConfigList, AcceptTimeout, Addr, Port)) of
@@ -188,47 +136,35 @@ init([ConfigFile, ConfigList, AcceptTimeout, Addr, Port, ListenInfo]) ->
{ok, State}
end.
-do_init(ConfigFile, ConfigList, AcceptTimeout, Addr, Port) ->
- IpFamily = proplists:get_value(ipfamily, ConfigList, inet6fb4),
+do_init(ConfigFile, ConfigList, _AcceptTimeout, Addr, Port) ->
+ Sup = httpd_util:make_name("httpd_connection_sup", Addr, Port),
NewConfigFile = proplists:get_value(file, ConfigList, ConfigFile),
ConfigDB = do_initial_store(ConfigList),
SocketType = httpd_conf:lookup_socket_type(ConfigDB),
- case httpd_acceptor_sup:start_acceptor(SocketType, Addr,
- Port, IpFamily, ConfigDB, AcceptTimeout) of
- {ok, _Pid} ->
- Status = [{max_conn, 0},
- {last_heavy_load, never},
- {last_connection, never}],
+ Status = [{max_conn, 0},
+ {last_heavy_load, never},
+ {last_connection, never}],
State = #state{socket_type = SocketType,
config_file = NewConfigFile,
config_db = ConfigDB,
- connections = [],
+ connection_sup = Sup,
status = Status},
- {ok, State};
- Else ->
- Else
- end.
+ {ok, State}.
-do_init(ConfigFile, ConfigList, AcceptTimeout, Addr, Port, ListenInfo) ->
- IpFamily = proplists:get_value(ipfamily, ConfigList, inet6fb4),
+do_init(ConfigFile, ConfigList, _AcceptTimeout, Addr, Port, _ListenInfo) ->
+ Sup = httpd_util:make_name("httpd_connection_sup", Addr, Port),
NewConfigFile = proplists:get_value(file, ConfigList, ConfigFile),
ConfigDB = do_initial_store(ConfigList),
SocketType = httpd_conf:lookup_socket_type(ConfigDB),
- case httpd_acceptor_sup:start_acceptor(SocketType, Addr,
- Port, IpFamily, ConfigDB,
- AcceptTimeout, ListenInfo) of
- {ok, _Pid} ->
- Status = [{max_conn,0}, {last_heavy_load,never},
- {last_connection,never}],
+ Status = [{max_conn,0}, {last_heavy_load,never},
+ {last_connection,never}],
State = #state{socket_type = SocketType,
config_file = NewConfigFile,
config_db = ConfigDB,
- connections = [],
+ connection_sup = Sup,
status = Status},
- {ok, State};
- Else ->
- Else
- end.
+ {ok, State}.
+
do_initial_store(ConfigList) ->
case httpd_conf:store(ConfigList) of
@@ -238,10 +174,6 @@ do_initial_store(ConfigList) ->
throw({error, Reason})
end.
-
-
-%% handle_call
-
handle_call(stop, _From, State) ->
{stop, normal, ok, State};
@@ -249,8 +181,7 @@ handle_call({config_match, Query}, _From, State) ->
Res = ets:match_object(State#state.config_db, Query),
{reply, Res, State};
-handle_call({reload, Conf}, _From, State)
- when State#state.admin_state =:= blocked ->
+handle_call({reload, Conf}, _From, #state{admin_state = blocked} = State) ->
case handle_reload(Conf, State) of
{stop, Reply,S1} ->
{stop, Reply, S1};
@@ -261,13 +192,32 @@ handle_call({reload, Conf}, _From, State)
handle_call({reload, _}, _From, State) ->
{reply,{error,{invalid_admin_state,State#state.admin_state}},State};
-handle_call(block, _From, State) ->
- {Reply,S1} = handle_block(State),
- {reply,Reply,S1};
+handle_call({block , Blocker, Mode, Timeout}, From,
+ #state{admin_state = unblocked,
+ connection_sup = CSup} = State) ->
+ Monitor = erlang:monitor(process, Blocker),
+ case count_children(CSup) of
+ 0 ->
+ %% Already in idle usage state => go directly to blocked
+ {reply, ok, State#state{admin_state = blocked,
+ blocker_ref = {Blocker, Monitor},
+ blocking_from = From}};
+ _ ->
+ handle_block(Mode, Timeout,
+ State#state{blocker_ref = {Blocker, Monitor},
+ blocking_from = From})
+ end;
+handle_call({block , _, _, _}, _, State) ->
+ {reply, {error, blocked}, State};
+
+handle_call({unblock, Blocker}, _, #state{blocker_ref = {Blocker,_},
+ admin_state = blocked} = State) ->
+
+ {reply, ok,
+ State#state{admin_state = unblocked, blocker_ref = undefined}};
-handle_call(unblock, {From,_Tag}, State) ->
- {Reply,S1} = handle_unblock(State,From),
- {reply, Reply, S1};
+handle_call({unblock, _}, _, State) ->
+ {reply, {error, only_blocker_may_unblock}, State};
handle_call({new_connection, Pid}, _From, State) ->
{Status, NewState} = handle_new_connection(State, Pid),
@@ -284,21 +234,6 @@ handle_call(Request, From, State) ->
report_error(State,String),
{reply, ok, State}.
-
-%% handle_cast
-
-handle_cast({done_connection, Pid}, State) ->
- S1 = handle_done_connection(State, Pid),
- {noreply, S1};
-
-handle_cast({block, disturbing, Timeout, From, Ref}, State) ->
- S1 = handle_block(State, Timeout, From, Ref),
- {noreply,S1};
-
-handle_cast({block, non_disturbing, Timeout, From, Ref}, State) ->
- S1 = handle_nd_block(State, Timeout, From, Ref),
- {noreply,S1};
-
handle_cast(Message, State) ->
String =
lists:flatten(
@@ -309,32 +244,51 @@ handle_cast(Message, State) ->
report_error(State, String),
{noreply, State}.
-%% handle_info
+handle_info(connections_terminated, #state{admin_state = shutting_down,
+ blocking_from = From} = State) ->
+ gen_server:reply(From, ok),
+ {noreply, State#state{admin_state = blocked, blocking_from = undefined,
+ blocker_ref = undefined}};
+handle_info(connections_terminated, State) ->
+ {noreply, State};
-handle_info({block_timeout, Method}, State) ->
- S1 = handle_block_timeout(State,Method),
- {noreply, S1};
+handle_info({block_timeout, non_disturbing},
+ #state{admin_state = shutting_down,
+ blocking_from = From,
+ blocker_ref = {_, Monitor}} = State) ->
+ erlang:demonitor(Monitor),
+ gen_server:reply(From, {error, timeout}),
+ {noreply, State#state{admin_state = unblocked, blocking_from = undefined,
+ blocker_ref = undefined}};
+handle_info({block_timeout, disturbing},
+ #state{admin_state = shutting_down,
+ blocking_from = From,
+ blocker_ref = {_, Monitor},
+ connection_sup = Sup} = State) ->
+ SupPid = whereis(Sup),
+ shutdown_connections(SupPid),
+ erlang:demonitor(Monitor),
+ gen_server:reply(From, ok),
+ {noreply, State#state{admin_state = blocked, blocker_ref = undefined,
+ blocking_from = undefined}};
+handle_info({block_timeout, _, _}, State) ->
+ {noreply, State};
-handle_info({'DOWN', Ref, process, _Object, _Info}, State) ->
- S1 =
- case State#state.blocker_ref of
- Ref ->
- handle_blocker_exit(State);
- _ ->
- %% Not our blocker, so ignore
- State
- end,
- {noreply, S1};
+handle_info({'DOWN', _, process, Pid, _Info},
+ #state{admin_state = Admin,
+ blocker_ref = {Pid, _}} = State) when
+ Admin =/= unblocked ->
+ {noreply, State#state{admin_state = unblocked,
+ blocking_from = undefined,
+ blocker_ref = undefined}};
+handle_info({'DOWN', _, process, _, _}, State) ->
+ {noreply, State};
handle_info({'EXIT', _, normal}, State) ->
{noreply, State};
-handle_info({'EXIT', _, blocked}, S) ->
- {noreply, S};
-
-handle_info({'EXIT', Pid, Reason}, State) ->
- S1 = check_connections(State, Pid, Reason),
- {noreply, S1};
+handle_info({'EXIT', _, shutdown}, State) ->
+ {stop, shutdown, State};
handle_info(Info, State) ->
String =
@@ -346,217 +300,66 @@ handle_info(Info, State) ->
report_error(State, String),
{noreply, State}.
-
-%% terminate
-
terminate(_, #state{config_db = Db}) ->
httpd_conf:remove_all(Db),
ok.
-
-%% code_change({down,ToVsn}, State, Extra)
-%%
-
code_change({down,_ToVsn}, State, _Extra) ->
{ok,State};
-%% code_change(FromVsn, State, Extra)
-%%
code_change(_FromVsn, State, _Extra) ->
{ok,State}.
-
-
-%% -------------------------------------------------------------------------
-%% check_connection
-%%
-%%
-%%
-%%
-
-check_connections(#state{connections = []} = State, _Pid, _Reason) ->
- State;
-check_connections(#state{connections = Connections} = State, Pid, _Reason) ->
- State#state{connections = lists:delete(Pid, Connections)}.
-
-
-%% -------------------------------------------------------------------------
-%% handle_[new | done]_connection
-%%
-%%
-%%
-%%
-
-handle_new_connection(State, Handler) ->
+%%%--------------------------------------------------------------------
+%%% Internal functions
+%%%--------------------------------------------------------------------
+handle_new_connection(#state{admin_state = AdminState} = State, Handler) ->
UsageState = get_ustate(State),
- AdminState = get_astate(State),
handle_new_connection(UsageState, AdminState, State, Handler).
-handle_new_connection(busy, unblocked, State, _Handler) ->
- Status = update_heavy_load_status(State#state.status),
- {{reject, busy},
- State#state{status = Status}};
-
-handle_new_connection(_UsageState, unblocked, State, Handler) ->
- Connections = State#state.connections,
- Status = update_connection_status(State#state.status,
- length(Connections)+1),
- link(Handler),
- {{ok, accept},
- State#state{connections = [Handler|Connections], status = Status}};
-
-handle_new_connection(_UsageState, _AdminState, State, _Handler) ->
- {{reject, blocked},
- State}.
-
-handle_done_connection(#state{admin_state = shutting_down,
- connections = Connections} = State, Handler) ->
- unlink(Handler),
- case lists:delete(Handler, Connections) of
- [] -> % Ok, block complete
- demonitor_blocker(State#state.blocker_ref),
- {Tmr,From,Ref} = State#state.blocking_tmr,
- stop_block_tmr(Tmr),
- From ! {block_reply,ok,Ref},
- State#state{admin_state = blocked, connections = [],
- blocker_ref = undefined};
- Connections1 ->
- State#state{connections = Connections1}
- end;
-
-handle_done_connection(#state{connections = Connections} = State, Handler) ->
- State#state{connections = lists:delete(Handler, Connections)}.
-
-
-%% -------------------------------------------------------------------------
-%% handle_block
-%%
-%%
-%%
-%%
-handle_block(#state{admin_state = AdminState} = S) ->
- handle_block(S, AdminState).
-
-handle_block(S,unblocked) ->
- %% Kill all connections
- [kill_handler(Pid) || Pid <- S#state.connections],
- {ok,S#state{connections = [], admin_state = blocked}};
-handle_block(S,blocked) ->
- {ok,S};
-handle_block(S,shutting_down) ->
- {{error,shutting_down},S}.
-
-
-kill_handler(Pid) ->
- exit(Pid, blocked).
-
-handle_block(S,Timeout,From,Ref) when Timeout >= 0 ->
- do_block(S,Timeout,From,Ref);
-
-handle_block(S,Timeout,From,Ref) ->
- Reply = {error,{invalid_block_request,Timeout}},
- From ! {block_reply,Reply,Ref},
- S.
-
-do_block(S,Timeout,From,Ref) ->
- case S#state.connections of
- [] ->
- %% Already in idle usage state => go directly to blocked
- From ! {block_reply,ok,Ref},
- S#state{admin_state = blocked};
- _ ->
- %% Active or Busy usage state => go to shutting_down
- %% Make sure we get to know if blocker dies...
- MonitorRef = monitor_blocker(From),
- Tmr = {start_block_tmr(Timeout,disturbing),From,Ref},
- S#state{admin_state = shutting_down,
- blocker_ref = MonitorRef, blocking_tmr = Tmr}
- end.
-
-handle_nd_block(S,infinity,From,Ref) ->
- do_nd_block(S,infinity,From,Ref);
-
-handle_nd_block(S,Timeout,From,Ref) when Timeout >= 0 ->
- do_nd_block(S,Timeout,From,Ref);
-
-handle_nd_block(S,Timeout,From,Ref) ->
- Reply = {error,{invalid_block_request,Timeout}},
- From ! {block_reply,Reply,Ref},
- S.
-
-do_nd_block(S,Timeout,From,Ref) ->
- case S#state.connections of
- [] ->
- %% Already in idle usage state => go directly to blocked
- From ! {block_reply,ok,Ref},
- S#state{admin_state = blocked};
+handle_new_connection(_UsageState, unblocked,
+ #state{config_db = Db, connection_sup = CSup} =
+ State, _) ->
+ Max = httpd_util:lookup(Db, max_clients),
+ case count_children(CSup) of
+ Count when Count =< Max ->
+ {{ok, accept}, State};
_ ->
- %% Active or Busy usage state => go to shutting_down
- %% Make sure we get to know if blocker dies...
- MonitorRef = monitor_blocker(From),
- Tmr = {start_block_tmr(Timeout,non_disturbing),From,Ref},
- S#state{admin_state = shutting_down,
- blocker_ref = MonitorRef, blocking_tmr = Tmr}
- end.
+ {{reject, busy}, State}
+ end;
-handle_block_timeout(S,Method) ->
- %% Time to take this to the road...
- demonitor_blocker(S#state.blocker_ref),
- handle_block_timeout1(S,Method,S#state.blocking_tmr).
-
-handle_block_timeout1(S,non_disturbing,{_,From,Ref}) ->
- From ! {block_reply,{error,timeout},Ref},
- S#state{admin_state = unblocked,
- blocker_ref = undefined, blocking_tmr = undefined};
-
-handle_block_timeout1(S,disturbing,{_,From,Ref}) ->
- [exit(Pid,blocked) || Pid <- S#state.connections],
-
- From ! {block_reply,ok,Ref},
- S#state{admin_state = blocked, connections = [],
- blocker_ref = undefined, blocking_tmr = undefined};
-
-handle_block_timeout1(S,Method,{_,From,Ref}) ->
- From ! {block_reply,{error,{unknown_block_method,Method}},Ref},
- S#state{admin_state = blocked, connections = [],
- blocker_ref = undefined, blocking_tmr = undefined};
-
-handle_block_timeout1(S, _Method, _TmrInfo) ->
- S#state{admin_state = unblocked,
- blocker_ref = undefined, blocking_tmr = undefined}.
-
-handle_unblock(S, FromA) ->
- handle_unblock(S, FromA, S#state.admin_state).
-
-handle_unblock(S, _FromA, unblocked) ->
- {ok,S};
-handle_unblock(S, FromA, _AdminState) ->
- case S#state.blocking_tmr of
- {Tmr,FromB,Ref} ->
- %% Another process is trying to unblock
- %% Inform the blocker
- stop_block_tmr(Tmr),
- FromB ! {block_reply, {error,{unblocked,FromA}},Ref};
- _ ->
- ok
- end,
- {ok,S#state{admin_state = unblocked, blocking_tmr = undefined}}.
-
-%% The blocker died so we give up on the block.
-handle_blocker_exit(S) ->
- {Tmr,_From,_Ref} = S#state.blocking_tmr,
- stop_block_tmr(Tmr),
- S#state{admin_state = unblocked,
- blocker_ref = undefined, blocking_tmr = undefined}.
+handle_new_connection(_UsageState, _AdminState, State, _Handler) ->
+ {{reject, blocked}, State}.
+
+handle_block(disturbing, infinity,
+ #state{connection_sup = CSup,
+ blocking_from = From,
+ blocker_ref = {_, Monitor}} = State) ->
+ SupPid = whereis(CSup),
+ shutdown_connections(SupPid),
+ erlang:demonitor(Monitor),
+ gen_server:reply(From, ok),
+ {noreply, State#state{admin_state = blocked, blocker_ref = undefined,
+ blocking_from = undefined}};
+handle_block(disturbing, Timeout, #state{connection_sup = CSup} = State) ->
+ Manager = self(),
+ spawn_link(fun() -> wait_for_shutdown(CSup, Manager) end),
+ erlang:send_after(Timeout, self(), {block_timeout, disturbing}),
+ {noreply, State#state{admin_state = shutting_down}};
+
+handle_block(non_disturbing, infinity,
+ #state{connection_sup = CSup} = State) ->
+ Manager = self(),
+ spawn_link(fun() -> wait_for_shutdown(CSup, Manager) end),
+ {noreply, State#state{admin_state = shutting_down}};
+
+handle_block(non_disturbing, Timeout,
+ #state{connection_sup = CSup} = State) ->
+ Manager = self(),
+ spawn_link(fun() -> wait_for_shutdown(CSup, Manager) end),
+ erlang:send_after(Timeout, self(), {block_timeout, non_disturbing}),
+ {noreply, State#state{admin_state = shutting_down}}.
-
-
-%% -------------------------------------------------------------------------
-%% handle_reload
-%%
-%%
-%%
-%%
handle_reload(undefined, #state{config_file = undefined} = State) ->
{continue, {error, undefined_config_file}, State};
handle_reload(undefined, #state{config_file = ConfigFile} = State) ->
@@ -632,7 +435,7 @@ check_constant_values(Db, Config) ->
%% Otherwise -> active
%%
get_ustate(State) ->
- get_ustate(length(State#state.connections),State).
+ get_ustate(count_children(State#state.connection_sup),State).
get_ustate(0,_State) ->
idle;
@@ -645,60 +448,6 @@ get_ustate(ConnectionCnt,State) ->
active
end.
-
-get_astate(S) -> S#state.admin_state.
-
-
-%% Timer handling functions
-start_block_tmr(infinity,_) ->
- undefined;
-start_block_tmr(T,M) ->
- erlang:send_after(T,self(),{block_timeout,M}).
-
-stop_block_tmr(undefined) ->
- ok;
-stop_block_tmr(Ref) ->
- erlang:cancel_timer(Ref).
-
-
-%% Monitor blocker functions
-monitor_blocker(Pid) when is_pid(Pid) ->
- case (catch erlang:monitor(process,Pid)) of
- {'EXIT', _Reason} ->
- undefined;
- MonitorRef ->
- MonitorRef
- end;
-monitor_blocker(_) ->
- undefined.
-
-demonitor_blocker(undefined) ->
- ok;
-demonitor_blocker(Ref) ->
- (catch erlang:demonitor(Ref)).
-
-
-%% Some status utility functions
-
-update_heavy_load_status(Status) ->
- update_status_with_time(Status,last_heavy_load).
-
-update_connection_status(Status,ConnCount) ->
- S1 = case lists:keysearch(max_conn,1,Status) of
- {value, {max_conn, C1}} when ConnCount > C1 ->
- lists:keyreplace(max_conn,1,Status,{max_conn,ConnCount});
- {value, {max_conn, _C2}} ->
- Status;
- false ->
- [{max_conn, ConnCount} | Status]
- end,
- update_status_with_time(S1,last_connection).
-
-update_status_with_time(Status,Key) ->
- lists:keyreplace(Key,1,Status,{Key,universal_time()}).
-
-universal_time() -> calendar:universal_time().
-
make_name(Addr,Port) ->
httpd_util:make_name("httpd",Addr,Port).
@@ -708,8 +457,7 @@ report_error(State,String) ->
error_logger:error_report(String),
mod_log:report_error(Cdb,String),
mod_disk_log:report_error(Cdb,String).
-
-%%
+
call(ServerRef, Request) ->
try gen_server:call(ServerRef, Request, infinity)
catch
@@ -717,11 +465,24 @@ call(ServerRef, Request) ->
{error, closed}
end.
-cast(ServerRef, Message) ->
- try gen_server:cast(ServerRef, Message)
- catch
- exit:_ ->
- {error, closed}
- end.
+count_children(Sup) ->
+ Children = supervisor:count_children(whereis(Sup)),
+ proplists:get_value(workers, Children).
+shutdown_connections(Sup) ->
+ Children = [Child || {_,Child,_,_} <- supervisor:which_children(Sup)],
+ lists:foreach(fun(Pid) -> exit(Pid, kill) end,
+ Children).
+
+wait_for_shutdown(CSup, Manager) ->
+ case count_children(CSup) of
+ 0 ->
+ Manager ! connections_terminated;
+ _ ->
+ receive
+ after 500 ->
+ ok
+ end,
+ wait_for_shutdown(CSup, Manager)
+ end.
diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl
index fb458f61cd..6f38090f58 100644
--- a/lib/inets/src/http_server/httpd_request_handler.erl
+++ b/lib/inets/src/http_server/httpd_request_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2014. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -25,7 +25,7 @@
-behaviour(gen_server).
%% Application internal API
--export([start/2, start/3, socket_ownership_transfered/3]).
+-export([start_link/2, start_link/3, socket_ownership_transfered/3]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
@@ -57,10 +57,10 @@
%% Description: Starts a httpd-request handler process. Intended to be
%% called by the httpd acceptor process.
%%--------------------------------------------------------------------
-start(Manager, ConfigDB) ->
- start(Manager, ConfigDB, 15000).
-start(Manager, ConfigDB, AcceptTimeout) ->
- proc_lib:start(?MODULE, init, [[Manager, ConfigDB,AcceptTimeout]]).
+start_link(Manager, ConfigDB) ->
+ start_link(Manager, ConfigDB, 15000).
+start_link(Manager, ConfigDB, AcceptTimeout) ->
+ proc_lib:start_link(?MODULE, init, [[Manager, ConfigDB,AcceptTimeout]]).
%%--------------------------------------------------------------------
@@ -87,34 +87,27 @@ socket_ownership_transfered(Pid, SocketType, Socket) ->
%% gen_server provides is needed.
%%--------------------------------------------------------------------
init([Manager, ConfigDB, AcceptTimeout]) ->
- ?hdrd("initiate",
- [{manager, Manager}, {cdb, ConfigDB}, {timeout, AcceptTimeout}]),
+ process_flag(trap_exit, true),
%% Make sure this process terminates if the httpd manager process
%% should die!
- link(Manager),
+ %%link(Manager),
%% At this point the function httpd_request_handler:start/2 will return.
proc_lib:init_ack({ok, self()}),
{SocketType, Socket} = await_socket_ownership_transfer(AcceptTimeout),
- ?hdrd("socket ownership transfered",
- [{socket_type, SocketType}, {socket, Socket}]),
TimeOut = httpd_util:lookup(ConfigDB, keep_alive_timeout, 150000),
Then = erlang:now(),
- ?hdrd("negotiate", []),
case http_transport:negotiate(SocketType, Socket, TimeOut) of
- {error, Error} ->
- ?hdrd("negotiation failed", [{error, Error}]),
+ {error, _Error} ->
exit(shutdown); %% Can be 'normal'.
ok ->
- ?hdrt("negotiation successfull", []),
NewTimeout = TimeOut - timer:now_diff(now(),Then) div 1000,
continue_init(Manager, ConfigDB, SocketType, Socket, NewTimeout)
end.
continue_init(Manager, ConfigDB, SocketType, Socket, TimeOut) ->
- ?hdrt("continue init", [{timeout, TimeOut}]),
Resolve = http_transport:resolve(),
Peername = httpd_socket:peername(SocketType, Socket),
@@ -139,14 +132,10 @@ continue_init(Manager, ConfigDB, SocketType, Socket, TimeOut) ->
max_keep_alive_request = NrOfRequest,
mfa = MFA},
- ?hdrt("activate request timeout", []),
-
- ?hdrt("set socket options (binary, packet & active)", []),
http_transport:setopts(SocketType, Socket,
[binary, {packet, 0}, {active, once}]),
NewState = data_receive_counter(activate_request_timeout(State), httpd_util:lookup(ConfigDB, minimum_bytes_per_second, false)),
- ?hdrt("init done", []),
- gen_server:enter_loop(?MODULE, [], NewState).
+ gen_server:enter_loop(?MODULE, [], NewState).
%%====================================================================
@@ -195,18 +184,13 @@ handle_cast(Msg, #state{mod = ModData} = State) ->
%% Description: Handling all non call/cast messages
%%--------------------------------------------------------------------
handle_info({Proto, Socket, Data},
- #state{mfa = {Module, Function, Args} = MFA,
+ #state{mfa = {Module, Function, Args},
mod = #mod{socket_type = SockType,
socket = Socket} = ModData} = State)
when (((Proto =:= tcp) orelse
(Proto =:= ssl) orelse
(Proto =:= dummy)) andalso is_binary(Data)) ->
- ?hdrd("received data",
- [{data, Data}, {proto, Proto},
- {socket, Socket}, {socket_type, SockType}, {mfa, MFA}]),
-
-%% case (catch Module:Function([Data | Args])) of
PROCESSED = (catch Module:Function([Data | Args])),
NewDataSize = case State#state.byte_limit of
undefined ->
@@ -214,10 +198,8 @@ handle_info({Proto, Socket, Data},
_ ->
State#state.data + byte_size(Data)
end,
- ?hdrt("data processed", [{processing_result, PROCESSED}]),
case PROCESSED of
{ok, Result} ->
- ?hdrd("data processed", [{result, Result}]),
NewState = case NewDataSize of
undefined ->
cancel_request_timeout(State);
@@ -227,7 +209,6 @@ handle_info({Proto, Socket, Data},
handle_http_msg(Result, NewState);
{error, {uri_too_long, MaxSize}, Version} ->
- ?hdrv("uri too long", [{max_size, MaxSize}, {version, Version}]),
NewModData = ModData#mod{http_version = Version},
httpd_response:send_status(NewModData, 414, "URI too long"),
Reason = io_lib:format("Uri too long, max size is ~p~n",
@@ -236,8 +217,6 @@ handle_info({Proto, Socket, Data},
{stop, normal, State#state{response_sent = true,
mod = NewModData}};
{error, {header_too_long, MaxSize}, Version} ->
- ?hdrv("header too long",
- [{max_size, MaxSize}, {version, Version}]),
NewModData = ModData#mod{http_version = Version},
httpd_response:send_status(NewModData, 413, "Header too long"),
Reason = io_lib:format("Header too long, max size is ~p~n",
@@ -246,7 +225,6 @@ handle_info({Proto, Socket, Data},
{stop, normal, State#state{response_sent = true,
mod = NewModData}};
NewMFA ->
- ?hdrd("data processed - reactivate socket", [{new_mfa, NewMFA}]),
http_transport:setopts(SockType, Socket, [{active, once}]),
case NewDataSize of
undefined ->
@@ -293,6 +271,10 @@ handle_info(check_data, #state{data = Data, byte_limit = Byte_Limit} = State) ->
_ ->
{stop, normal, State#state{response_sent = true}}
end;
+
+handle_info({'EXIT', _, Reason}, State) ->
+ {stop, Reason, State};
+
%% Default case
handle_info(Info, #state{mod = ModData} = State) ->
Error = lists:flatten(
@@ -324,10 +306,8 @@ terminate(Reason, #state{response_sent = false, mod = ModData} = State) ->
terminate(_Reason, State) ->
do_terminate(State).
-do_terminate(#state{mod = ModData, manager = Manager} = State) ->
- catch httpd_manager:done_connection(Manager),
+do_terminate(#state{mod = ModData} = State) ->
cancel_request_timeout(State),
- %% receive after 5000 -> ok end,
httpd_socket:close(ModData#mod.socket_type, ModData#mod.socket).
@@ -355,30 +335,24 @@ await_socket_ownership_transfer(AcceptTimeout) ->
handle_http_msg({_, _, Version, {_, _}, _},
#state{status = busy, mod = ModData} = State) ->
- ?hdrt("handle http msg when manager busy", [{mod, ModData}]),
handle_manager_busy(State#state{mod =
ModData#mod{http_version = Version}}),
{stop, normal, State};
handle_http_msg({_, _, Version, {_, _}, _},
#state{status = blocked, mod = ModData} = State) ->
- ?hdrt("handle http msg when manager blocket", [{mod, ModData}]),
handle_manager_blocked(State#state{mod =
ModData#mod{http_version = Version}}),
{stop, normal, State};
handle_http_msg({Method, Uri, Version, {RecordHeaders, Headers}, Body},
#state{status = accept, mod = ModData} = State) ->
- ?hdrt("handle http msg when manager accepting",
- [{method, Method}, {mod, ModData}]),
case httpd_request:validate(Method, Uri, Version) of
ok ->
- ?hdrt("request validated", []),
{ok, NewModData} =
httpd_request:update_mod_data(ModData, Method, Uri,
Version, Headers),
- ?hdrt("new mod data", [{mod, NewModData}]),
case is_host_specified_if_required(NewModData#mod.absolute_uri,
RecordHeaders, Version) of
true ->
@@ -392,23 +366,18 @@ handle_http_msg({Method, Uri, Version, {RecordHeaders, Headers}, Body},
{stop, normal, State#state{response_sent = true}}
end;
{error, {not_supported, What}} ->
- ?hdrd("validation failed: not supported", [{what, What}]),
httpd_response:send_status(ModData#mod{http_version = Version},
501, {Method, Uri, Version}),
Reason = io_lib:format("Not supported: ~p~n", [What]),
error_log(Reason, ModData),
{stop, normal, State#state{response_sent = true}};
{error, {bad_request, {forbidden, URI}}} ->
- ?hdrd("validation failed: bad request - forbidden",
- [{uri, URI}]),
httpd_response:send_status(ModData#mod{http_version = Version},
403, URI),
Reason = io_lib:format("Forbidden URI: ~p~n", [URI]),
error_log(Reason, ModData),
{stop, normal, State#state{response_sent = true}};
{error, {bad_request, {malformed_syntax, URI}}} ->
- ?hdrd("validation failed: bad request - malformed syntax",
- [{uri, URI}]),
httpd_response:send_status(ModData#mod{http_version = Version},
400, URI),
Reason = io_lib:format("Malformed syntax in URI: ~p~n", [URI]),
@@ -417,12 +386,9 @@ handle_http_msg({Method, Uri, Version, {RecordHeaders, Headers}, Body},
end;
handle_http_msg({ChunkedHeaders, Body},
State = #state{headers = Headers}) ->
- ?hdrt("handle http msg",
- [{chunked_headers, ChunkedHeaders}, {body, Body}]),
NewHeaders = http_chunk:handle_headers(Headers, ChunkedHeaders),
handle_response(State#state{headers = NewHeaders, body = Body});
handle_http_msg(Body, State) ->
- ?hdrt("handle http msg", [{body, Body}]),
handle_response(State#state{body = Body}).
handle_manager_busy(#state{mod = #mod{config_db = ConfigDB}} = State) ->
@@ -445,7 +411,6 @@ is_host_specified_if_required(_, _, _) ->
true.
handle_body(#state{mod = #mod{config_db = ConfigDB}} = State) ->
- ?hdrt("handle body", []),
MaxHeaderSize = max_header_size(ConfigDB),
MaxBodySize = max_body_size(ConfigDB),
@@ -459,34 +424,22 @@ handle_body(#state{mod = #mod{config_db = ConfigDB}} = State) ->
handle_body(#state{headers = Headers, body = Body, mod = ModData} = State,
MaxHeaderSize, MaxBodySize) ->
- ?hdrt("handle body", [{headers, Headers}, {body, Body}]),
case Headers#http_request_h.'transfer-encoding' of
"chunked" ->
- ?hdrt("chunked - attempt decode", []),
case http_chunk:decode(Body, MaxBodySize, MaxHeaderSize) of
{Module, Function, Args} ->
- ?hdrt("chunk decoded",
- [{module, Module},
- {function, Function},
- {args, Args}]),
http_transport:setopts(ModData#mod.socket_type,
ModData#mod.socket,
[{active, once}]),
{noreply, State#state{mfa =
{Module, Function, Args}}};
{ok, {ChunkedHeaders, NewBody}} ->
- ?hdrt("chunk decoded",
- [{chunked_headers, ChunkedHeaders},
- {new_body, NewBody}]),
NewHeaders =
http_chunk:handle_headers(Headers, ChunkedHeaders),
- ?hdrt("chunked - headers handled",
- [{new_headers, NewHeaders}]),
handle_response(State#state{headers = NewHeaders,
body = NewBody})
end;
Encoding when is_list(Encoding) ->
- ?hdrt("not chunked - encoding", [{encoding, Encoding}]),
httpd_response:send_status(ModData, 501,
"Unknown Transfer-Encoding"),
Reason = io_lib:format("Unknown Transfer-Encoding: ~p~n",
@@ -494,17 +447,12 @@ handle_body(#state{headers = Headers, body = Body, mod = ModData} = State,
error_log(Reason, ModData),
{stop, normal, State#state{response_sent = true}};
_ ->
- ?hdrt("not chunked", []),
Length =
list_to_integer(Headers#http_request_h.'content-length'),
case ((Length =< MaxBodySize) or (MaxBodySize == nolimit)) of
true ->
case httpd_request:whole_body(Body, Length) of
{Module, Function, Args} ->
- ?hdrt("whole body",
- [{module, Module},
- {function, Function},
- {args, Args}]),
http_transport:setopts(ModData#mod.socket_type,
ModData#mod.socket,
[{active, once}]),
@@ -512,15 +460,11 @@ handle_body(#state{headers = Headers, body = Body, mod = ModData} = State,
{Module, Function, Args}}};
{ok, NewBody} ->
- ?hdrt("whole body",
- [{new_body, NewBody}]),
handle_response(
State#state{headers = Headers,
body = NewBody})
end;
false ->
- ?hdrd("body too long",
- [{length, Length}, {max_body_size, MaxBodySize}]),
httpd_response:send_status(ModData, 413, "Body too long"),
error_log("Body too long", ModData),
{stop, normal, State#state{response_sent = true}}
@@ -582,8 +526,6 @@ handle_response(#state{body = Body,
mod = ModData,
headers = Headers,
max_keep_alive_request = Max} = State) when Max > 0 ->
- ?hdrt("handle response",
- [{body, Body}, {mod, ModData}, {headers, Headers}, {max, Max}]),
{NewBody, Data} = httpd_request:body_data(Headers, Body),
ok = httpd_response:generate_and_send_response(
ModData#mod{entity_body = NewBody}),
@@ -592,8 +534,6 @@ handle_response(#state{body = Body,
handle_response(#state{body = Body,
headers = Headers,
mod = ModData} = State) ->
- ?hdrt("handle response",
- [{body, Body}, {mod, ModData}, {headers, Headers}]),
{NewBody, _} = httpd_request:body_data(Headers, Body),
ok = httpd_response:generate_and_send_response(
ModData#mod{entity_body = NewBody}),
@@ -601,7 +541,6 @@ handle_response(#state{body = Body,
handle_next_request(#state{mod = #mod{connection = true} = ModData,
max_keep_alive_request = Max} = State, Data) ->
- ?hdrt("handle next request", [{max, Max}]),
NewModData = #mod{socket_type = ModData#mod.socket_type,
socket = ModData#mod.socket,
@@ -630,11 +569,9 @@ handle_next_request(#state{mod = #mod{connection = true} = ModData,
end;
handle_next_request(State, _) ->
- ?hdrt("handle next request - stop", []),
{stop, normal, State}.
activate_request_timeout(#state{timeout = Time} = State) ->
- ?hdrt("activate request timeout", [{time, Time}]),
Ref = erlang:send_after(Time, self(), timeout),
State#state{timer = Ref}.
data_receive_counter(State, Byte_limit) ->
diff --git a/lib/inets/src/inets_app/inets.app.src b/lib/inets/src/inets_app/inets.app.src
index 4aea2ef3d7..a6dd364c2d 100644
--- a/lib/inets/src/inets_app/inets.app.src
+++ b/lib/inets/src/inets_app/inets.app.src
@@ -1,7 +1,7 @@
%% This is an -*- erlang -*- file.
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2014. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -59,6 +59,7 @@
httpd_acceptor,
httpd_acceptor_sup,
httpd_cgi,
+ httpd_connection_sup,
httpd_conf,
httpd_esi,
httpd_example,