From fbd680f0f6fb5fe99c4345b838cb42aa1afb3283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Sat, 8 Feb 2025 14:53:54 +0100 Subject: [PATCH] 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. --- src/cowboy_stream_h.erl | 7 +++---- test/handlers/crash_h.erl | 3 +++ test/plain_handler_SUITE.erl | 11 +++++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/cowboy_stream_h.erl b/src/cowboy_stream_h.erl index b373344eb..e384eb07e 100644 --- a/src/cowboy_stream_h.erl +++ b/src/cowboy_stream_h.erl @@ -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 diff --git a/test/handlers/crash_h.erl b/test/handlers/crash_h.erl index b687ababf..57d4d85b0 100644 --- a/test/handlers/crash_h.erl +++ b/test/handlers/crash_h.erl @@ -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); diff --git a/test/plain_handler_SUITE.erl b/test/plain_handler_SUITE.erl index 756c0a610..2dc1e2387 100644 --- a/test/plain_handler_SUITE.erl +++ b/test/plain_handler_SUITE.erl @@ -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).