0
Fork 0
mirror of https://github.com/ninenines/cowboy.git synced 2025-07-14 04:10:24 +00:00

Properly handle external exits of request processes

Because the exit reason doesn't include the stacktrace they
were ignored. Now they are properly handled. The error message
was changed slightly to accomodate.
This commit is contained in:
Loïc Hoguin 2025-02-08 14:53:54 +01:00
parent cc97c770fb
commit fbd680f0f6
No known key found for this signature in database
GPG key ID: 8A9DF795F6FED764
3 changed files with 17 additions and 4 deletions

View file

@ -138,7 +138,7 @@ info(StreamID, Info={'EXIT', Pid, {{request_error, Reason, _HumanReadable}, _}},
{error_response, Status, #{<<"content-length">> => <<"0">>}, <<>>},
stop
], State);
info(StreamID, Exit={'EXIT', Pid, {Reason, Stacktrace}}, State=#state{ref=Ref, pid=Pid}) ->
info(StreamID, Exit={'EXIT', Pid, Reason}, State=#state{ref=Ref, pid=Pid}) ->
Commands0 = [{internal_error, Exit, 'Stream process crashed.'}],
Commands = case Reason of
normal -> Commands0;
@ -146,9 +146,8 @@ info(StreamID, Exit={'EXIT', Pid, {Reason, Stacktrace}}, State=#state{ref=Ref, p
{shutdown, _} -> Commands0;
_ -> [{log, error,
"Ranch listener ~p, connection process ~p, stream ~p "
"had its request process ~p exit with reason "
"~999999p and stacktrace ~999999p~n",
[Ref, self(), StreamID, Pid, Reason, Stacktrace]}
"had its request process ~p exit with reason ~0p~n",
[Ref, self(), StreamID, Pid, Reason]}
|Commands0]
end,
%% @todo We are trying to send a 500 response before resetting

View file

@ -7,6 +7,9 @@
-export([init/2]).
-spec init(_, _) -> no_return().
init(_, external_exit) ->
ct_helper:ignore(?MODULE, init, 2),
exit(self(), ct_helper_ignore);
init(_, no_reply) ->
ct_helper:ignore(?MODULE, init, 2),
error(crash);

View file

@ -45,6 +45,7 @@ end_per_group(Name, _) ->
init_dispatch(_) ->
cowboy_router:compile([{"localhost", [
{"/crash/external_exit", crash_h, external_exit},
{"/crash/no_reply", crash_h, no_reply},
{"/crash/reply", crash_h, reply}
]}]).
@ -78,3 +79,13 @@ crash_before_reply(Config) ->
]),
{response, fin, 500, _} = gun:await(ConnPid, Ref),
gun:close(ConnPid).
external_exit_before_reply(Config) ->
doc("A plain handler exits externally before a response was sent "
"results in a 500 response."),
ConnPid = gun_open(Config),
Ref = gun:get(ConnPid, "/crash/external_exit", [
{<<"accept-encoding">>, <<"gzip">>}
]),
{response, fin, 500, _} = gun:await(ConnPid, Ref),
gun:close(ConnPid).