File 0801-inets-httpd-avoid-function_clause-during-startup.patch of Package erlang
From 245b210e368d9d930b8fff0e8bbdb1b083112dc0 Mon Sep 17 00:00:00 2001
From: Jakub Witczak <kuba@erlang.org>
Date: Tue, 25 Jul 2023 15:12:55 +0200
Subject: [PATCH] inets: httpd avoid function_clause during startup
- avoid function_clause httpd_request:body_data/2
- happening when httpd is stopped during TLS negotiation
- in such cases Manager process is killed and then continue_init fails
---
lib/inets/src/http_server/httpd_manager.erl | 14 ++++-
.../src/http_server/httpd_request_handler.erl | 56 +++++++++++--------
2 files changed, 44 insertions(+), 26 deletions(-)
diff --git a/lib/inets/src/http_server/httpd_manager.erl b/lib/inets/src/http_server/httpd_manager.erl
index d198bc8fbf..fe7f721345 100644
--- a/lib/inets/src/http_server/httpd_manager.erl
+++ b/lib/inets/src/http_server/httpd_manager.erl
@@ -454,8 +454,18 @@ report_error(State,String) ->
call(ServerRef, Request) ->
try gen_server:call(ServerRef, Request, infinity)
catch
- exit:_ ->
- {error, closed}
+ exit:Reason:Stacktrace ->
+ String =
+ lists:flatten(
+ io_lib:format(
+ "Request"
+ "~n ~p"
+ "~nto manager (~p) from ~p failed:"
+ "~n ~p"
+ "~n ~p",
+ [Request, ServerRef, self(), Reason, Stacktrace])),
+ error_logger:warning_report(String),
+ {error, Reason}
end.
count_children(Sup) ->
diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl
index 26327a2567..9231c5e584 100644
--- a/lib/inets/src/http_server/httpd_request_handler.erl
+++ b/lib/inets/src/http_server/httpd_request_handler.erl
@@ -137,34 +137,42 @@ continue_init(Manager, ConfigDB, SocketType, Socket, Peername, Sockname,
socket_type = SocketType,
socket = Socket,
init_data = InitData},
-
- MaxHeaderSize = max_header_size(ConfigDB),
- MaxURISize = max_uri_size(ConfigDB),
- NrOfRequest = max_keep_alive_request(ConfigDB),
+
+ MaxHeaderSize = max_header_size(ConfigDB),
+ MaxURISize = max_uri_size(ConfigDB),
+ NrOfRequest = max_keep_alive_request(ConfigDB),
MaxContentLen = max_content_length(ConfigDB),
Customize = customize(ConfigDB),
MaxChunk = max_client_body_chunk(ConfigDB),
-
- {_, Status} = httpd_manager:new_connection(Manager),
-
- MFA = {httpd_request, parse, [[{max_uri, MaxURISize}, {max_header, MaxHeaderSize},
- {max_version, ?HTTP_MAX_VERSION_STRING},
- {max_method, ?HTTP_MAX_METHOD_STRING},
- {max_content_length, MaxContentLen},
- {customize, Customize}
- ]]},
-
- State = #state{mod = Mod,
- manager = Manager,
- status = Status,
- timeout = TimeOut,
- max_keep_alive_request = NrOfRequest,
- mfa = MFA,
- chunk = chunk_start(MaxChunk)},
- setopts(Socket, SocketType, [binary, {packet, 0}, {active, once}]),
- NewState = data_receive_counter(activate_request_timeout(State), httpd_util:lookup(ConfigDB, minimum_bytes_per_second, false)),
- gen_server:enter_loop(?MODULE, [], NewState).
+ {Result, Status} = httpd_manager:new_connection(Manager),
+ case Result of
+ error ->
+ httpd_util:error_log(ConfigDB,
+ httpd_logger:error_report('TLS', Status,
+ Mod, ?LOCATION)),
+ exit({shutdown, Status});
+ _ ->
+ MFA = {httpd_request, parse, [[{max_uri, MaxURISize}, {max_header, MaxHeaderSize},
+ {max_version, ?HTTP_MAX_VERSION_STRING},
+ {max_method, ?HTTP_MAX_METHOD_STRING},
+ {max_content_length, MaxContentLen},
+ {customize, Customize}
+ ]]},
+
+ State = #state{mod = Mod,
+ manager = Manager,
+ status = Status,
+ timeout = TimeOut,
+ max_keep_alive_request = NrOfRequest,
+ mfa = MFA,
+ chunk = chunk_start(MaxChunk)},
+ setopts(Socket, SocketType, [binary, {packet, 0}, {active, once}]),
+ NewState =
+ data_receive_counter(activate_request_timeout(State),
+ httpd_util:lookup(ConfigDB, minimum_bytes_per_second, false)),
+ gen_server:enter_loop(?MODULE, [], NewState)
+ end.
%%====================================================================
%% gen_server callbacks
--
2.35.3