aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2011-05-20 01:28:55 +0200
committerLoïc Hoguin <[email protected]>2011-05-20 01:28:55 +0200
commit4c4030a792a94d96f8bda5076fcfdc03a590030e (patch)
tree82d97feff6f25c1441f814e0e7ce06ab52f89f4d
parent548a9a15b8b75ffd029e919fbf1352486454dfb7 (diff)
downloadcowboy-4c4030a792a94d96f8bda5076fcfdc03a590030e.tar.gz
cowboy-4c4030a792a94d96f8bda5076fcfdc03a590030e.tar.bz2
cowboy-4c4030a792a94d96f8bda5076fcfdc03a590030e.zip
Send a meaningful error to error_logger on handler crashes.
Inspired by gen_server and friends. Should fix issue #13.
-rw-r--r--src/cowboy_http_protocol.erl59
1 files 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.