diff options
author | Loïc Hoguin <[email protected]> | 2011-07-06 20:00:08 +0200 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2011-07-06 20:00:08 +0200 |
commit | aa0a66749e23fe8d29421794ce8ab173b062a311 (patch) | |
tree | 2c1a50f9c0ca4475495c5760be53fcf45294e71d /src | |
parent | 108a491f5515fdc2a7fe3ce8c310a261d6be3230 (diff) | |
download | cowboy-aa0a66749e23fe8d29421794ce8ab173b062a311.tar.gz cowboy-aa0a66749e23fe8d29421794ce8ab173b062a311.tar.bz2 cowboy-aa0a66749e23fe8d29421794ce8ab173b062a311.zip |
Move recursion out of a try .. catch block.
Fixes issue #31.
Recursion shouldn't happen in a single catch statement or inside
a try .. catch statement. The only safe construct for catching
exceptions and perform recursion when everything goes well is
to put the recursive call inside a try .. of .. catch construct
in the of .. catch block.
Otherwise the stack gets filled with exception-related information
since they can still be caught if we were to send them and unfold
the whole thing.
Thanks go to lpgauth for reporting the issue and people on IRC
for explaining the hows and whys.
Diffstat (limited to 'src')
-rw-r--r-- | src/cowboy_http_protocol.erl | 25 |
1 files changed, 12 insertions, 13 deletions
diff --git a/src/cowboy_http_protocol.erl b/src/cowboy_http_protocol.erl index 779866a..837d837 100644 --- a/src/cowboy_http_protocol.erl +++ b/src/cowboy_http_protocol.erl @@ -223,25 +223,24 @@ handler_loop(HandlerState, Req, State=#state{handler={Handler, Opts}}) -> -spec handler_terminate(any(), #http_req{}, #state{}) -> ok. handler_terminate(HandlerState, Req=#http_req{buffer=Buffer}, State=#state{handler={Handler, Opts}}) -> - try - HandlerRes = Handler:terminate(Req#http_req{resp_state=locked}, - HandlerState), - BodyRes = ensure_body_processed(Req), - RespRes = ensure_response(Req, State), - case {HandlerRes, BodyRes, RespRes, State#state.connection} of - {ok, ok, ok, keepalive} -> - ?MODULE:parse_request(State#state{buffer=Buffer}); - _Closed -> - terminate(State) - end + HandlerRes = try + Handler:terminate(Req#http_req{resp_state=locked}, HandlerState) catch Class:Reason -> - terminate(State), error_logger:error_msg( "** Handler ~p terminating in terminate/2 for the reason ~p:~p~n" "** Options were ~p~n** Handler state was ~p~n" "** Request was ~p~n** Stacktrace: ~p~n~n", [Handler, Class, Reason, Opts, - HandlerState, Req, erlang:get_stacktrace()]) + HandlerState, Req, erlang:get_stacktrace()]), + error + end, + BodyRes = ensure_body_processed(Req), + RespRes = ensure_response(Req, State), + case {HandlerRes, BodyRes, RespRes, State#state.connection} of + {ok, ok, ok, keepalive} -> + ?MODULE:parse_request(State#state{buffer=Buffer}); + _Closed -> + terminate(State) end. -spec ensure_body_processed(#http_req{}) -> ok | close. |