From 4c4030a792a94d96f8bda5076fcfdc03a590030e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Fri, 20 May 2011 01:28:55 +0200 Subject: Send a meaningful error to error_logger on handler crashes. Inspired by gen_server and friends. Should fix issue #13. --- src/cowboy_http_protocol.erl | 59 +++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/src/cowboy_http_protocol.erl b/src/cowboy_http_protocol.erl index ed4d963..4f5ac9f 100644 --- a/src/cowboy_http_protocol.erl +++ b/src/cowboy_http_protocol.erl @@ -172,40 +172,59 @@ dispatch(Req=#http_req{host=Host, path=Path}, -spec handler_init(Req::#http_req{}, State::#state{}) -> ok. handler_init(Req, State=#state{ transport=Transport, handler={Handler, Opts}}) -> - case catch Handler:init({Transport:name(), http}, Req, Opts) of + try Handler:init({Transport:name(), http}, Req, Opts) of {ok, Req2, HandlerState} -> handler_loop(HandlerState, Req2, State); %% @todo {upgrade, transport, Module} {upgrade, protocol, Module} -> - Module:upgrade(Handler, Opts, Req); - {'EXIT', _Reason} -> - error_terminate(500, State) + Module:upgrade(Handler, Opts, Req) + catch Class:Reason -> + error_terminate(500, State), + error_logger:error_msg( + "** Handler ~p terminating in init/3 for the reason ~p:~p~n" + "** Options were ~p~n** Request was ~p~n** Stacktrace: ~p~n~n", + [Handler, Class, Reason, Opts, Req, erlang:get_stacktrace()]) end. -spec handler_loop(HandlerState::term(), Req::#http_req{}, State::#state{}) -> ok. -handler_loop(HandlerState, Req, State=#state{handler={Handler, _Opts}}) -> - case catch Handler:handle(Req#http_req{resp_state=waiting}, - HandlerState) of +handler_loop(HandlerState, Req, State=#state{handler={Handler, Opts}}) -> + try Handler:handle(Req#http_req{resp_state=waiting}, HandlerState) of {ok, Req2, HandlerState2} -> - handler_terminate(HandlerState2, Req2, State); - {'EXIT', _Reason} -> - terminate(State) + handler_terminate(HandlerState2, Req2, State) + catch Class:Reason -> + terminate(State), + error_logger:error_msg( + "** Handler ~p terminating in handle/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()]) end. -spec handler_terminate(HandlerState::term(), Req::#http_req{}, State::#state{}) -> ok. handler_terminate(HandlerState, Req=#http_req{buffer=Buffer}, - State=#state{handler={Handler, _Opts}}) -> - HandlerRes = (catch 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) + 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 + 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()]) end. -spec ensure_body_processed(Req::#http_req{}) -> ok | close. -- cgit v1.2.3