aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2013-01-22 02:34:18 +0100
committerLoïc Hoguin <[email protected]>2013-01-22 02:34:18 +0100
commit647e95aed157edd58c86acdd774048593eb9d039 (patch)
tree07b4877b2d59a9c694d091eaa00c03d0b1dc4c80 /src
parent297ae32af1ad9b84558c4338f6caf82665d448e0 (diff)
downloadcowboy-647e95aed157edd58c86acdd774048593eb9d039.tar.gz
cowboy-647e95aed157edd58c86acdd774048593eb9d039.tar.bz2
cowboy-647e95aed157edd58c86acdd774048593eb9d039.zip
Replace terminate/2 with terminate/3, adding a Reason
This should have been done a *long* time ago, back when I initially added Websocket support. This is the first part of two in improving loop handler support with regards to socket closure. Reason may include: {normal, shutdown} for the most normal shutdown, {normal, timeout} for a loop handler timeout shutdown, or {error, _} if an error occured.
Diffstat (limited to 'src')
-rw-r--r--src/cowboy_handler.erl34
-rw-r--r--src/cowboy_http_handler.erl9
-rw-r--r--src/cowboy_loop_handler.erl9
3 files changed, 32 insertions, 20 deletions
diff --git a/src/cowboy_handler.erl b/src/cowboy_handler.erl
index cc871d9..4acb876 100644
--- a/src/cowboy_handler.erl
+++ b/src/cowboy_handler.erl
@@ -64,7 +64,8 @@ handler_init(Req, State, Handler, HandlerOpts) ->
handler_before_loop(Req2, State#state{
hibernate=true, loop_timeout=Timeout}, Handler, HandlerState);
{shutdown, Req2, HandlerState} ->
- terminate_request(Req2, State, Handler, HandlerState);
+ terminate_request(Req2, State, Handler, HandlerState,
+ {normal, shutdown});
%% @todo {upgrade, transport, Module}
{upgrade, protocol, Module} ->
upgrade_protocol(Req, State, Handler, HandlerOpts, Module);
@@ -99,7 +100,8 @@ upgrade_protocol(Req, #state{env=Env},
handler_handle(Req, State, Handler, HandlerState) ->
try Handler:handle(Req, HandlerState) of
{ok, Req2, HandlerState2} ->
- terminate_request(Req2, State, Handler, HandlerState2)
+ terminate_request(Req2, State, Handler, HandlerState2,
+ {normal, shutdown})
catch Class:Reason ->
error_logger:error_msg(
"** Cowboy handler ~p terminating in ~p/~p~n"
@@ -109,7 +111,7 @@ handler_handle(Req, State, Handler, HandlerState) ->
"** Stacktrace: ~p~n~n",
[Handler, handle, 2, Class, Reason, HandlerState,
cowboy_req:to_list(Req), erlang:get_stacktrace()]),
- handler_terminate(Req, Handler, HandlerState),
+ handler_terminate(Req, Handler, HandlerState, Reason),
{error, 500, Req}
end.
@@ -146,7 +148,8 @@ handler_loop_timeout(State=#state{loop_timeout=Timeout,
handler_loop(Req, State=#state{loop_timeout_ref=TRef}, Handler, HandlerState) ->
receive
{timeout, TRef, ?MODULE} ->
- terminate_request(Req, State, Handler, HandlerState);
+ terminate_request(Req, State, Handler, HandlerState,
+ {normal, timeout});
{timeout, OlderTRef, ?MODULE} when is_reference(OlderTRef) ->
handler_loop(Req, State, Handler, HandlerState);
Message ->
@@ -160,7 +163,8 @@ handler_loop(Req, State=#state{loop_timeout_ref=TRef}, Handler, HandlerState) ->
handler_call(Req, State, Handler, HandlerState, Message) ->
try Handler:info(Message, Req, HandlerState) of
{ok, Req2, HandlerState2} ->
- terminate_request(Req2, State, Handler, HandlerState2);
+ terminate_request(Req2, State, Handler, HandlerState2,
+ {normal, shutdown});
{loop, Req2, HandlerState2} ->
handler_before_loop(Req2, State, Handler, HandlerState2);
{loop, Req2, HandlerState2, hibernate} ->
@@ -175,27 +179,29 @@ handler_call(Req, State, Handler, HandlerState, Message) ->
"** Stacktrace: ~p~n~n",
[Handler, info, 3, Class, Reason, HandlerState,
cowboy_req:to_list(Req), erlang:get_stacktrace()]),
- handler_terminate(Req, Handler, HandlerState),
+ handler_terminate(Req, Handler, HandlerState, Reason),
{error, 500, Req}
end.
--spec terminate_request(Req, #state{}, module(), any()) ->
+-spec terminate_request(Req, #state{}, module(), any(),
+ {normal, timeout | shutdown} | {error, atom()}) ->
{ok, Req, cowboy_middleware:env()} when Req::cowboy_req:req().
-terminate_request(Req, #state{env=Env}, Handler, HandlerState) ->
- HandlerRes = handler_terminate(Req, Handler, HandlerState),
+terminate_request(Req, #state{env=Env}, Handler, HandlerState, Reason) ->
+ HandlerRes = handler_terminate(Req, Handler, HandlerState, Reason),
{ok, Req, [{result, HandlerRes}|Env]}.
--spec handler_terminate(cowboy_req:req(), module(), any()) -> ok.
-handler_terminate(Req, Handler, HandlerState) ->
+-spec handler_terminate(cowboy_req:req(), module(), any(),
+ {normal, timeout | shutdown} | {error, atom()}) -> ok.
+handler_terminate(Req, Handler, HandlerState, Reason) ->
try
- Handler:terminate(cowboy_req:lock(Req), HandlerState)
- catch Class:Reason ->
+ Handler:terminate(Reason, cowboy_req:lock(Req), HandlerState)
+ catch Class:Reason2 ->
error_logger:error_msg(
"** Cowboy handler ~p terminating in ~p/~p~n"
" for the reason ~p:~p~n"
"** Handler state was ~p~n"
"** Request was ~p~n"
"** Stacktrace: ~p~n~n",
- [Handler, terminate, 2, Class, Reason, HandlerState,
+ [Handler, terminate, 3, Class, Reason2, HandlerState,
cowboy_req:to_list(Req), erlang:get_stacktrace()])
end.
diff --git a/src/cowboy_http_handler.erl b/src/cowboy_http_handler.erl
index fa52f78..9c7aaa6 100644
--- a/src/cowboy_http_handler.erl
+++ b/src/cowboy_http_handler.erl
@@ -22,8 +22,8 @@
%% <em>handle/2</em> allows you to handle the request. It receives the
%% state previously defined.
%%
-%% <em>terminate/2</em> allows you to clean up. It receives the state
-%% previously defined.
+%% <em>terminate/3</em> allows you to clean up. It receives the
+%% termination reason and the state previously defined.
%%
%% There is no required operation to perform in any of these callbacks
%% other than returning the proper values. Make sure you always return
@@ -33,6 +33,9 @@
-type opts() :: any().
-type state() :: any().
+-type terminate_reason() :: {normal, shutdown}
+ | {normal, timeout} %% Only occurs in loop handlers.
+ | {error, atom()}.
-callback init({atom(), http}, Req, opts())
-> {ok, Req, state()}
@@ -45,4 +48,4 @@
when Req::cowboy_req:req().
-callback handle(Req, State) -> {ok, Req, State}
when Req::cowboy_req:req(), State::state().
--callback terminate(cowboy_req:req(), state()) -> ok.
+-callback terminate(terminate_reason(), cowboy_req:req(), state()) -> ok.
diff --git a/src/cowboy_loop_handler.erl b/src/cowboy_loop_handler.erl
index 067d672..71323d2 100644
--- a/src/cowboy_loop_handler.erl
+++ b/src/cowboy_loop_handler.erl
@@ -23,8 +23,8 @@
%% receive. It receives the message and the state previously defined.
%% It can decide to stop the receive loop or continue receiving.
%%
-%% <em>terminate/2</em> allows you to clean up. It receives the state
-%% previously defined.
+%% <em>terminate/3</em> allows you to clean up. It receives the
+%% termination reason and the state previously defined.
%%
%% There is no required operation to perform in any of these callbacks
%% other than returning the proper values. Make sure you always return
@@ -39,6 +39,9 @@
-type opts() :: any().
-type state() :: any().
+-type terminate_reason() :: {normal, shutdown}
+ | {normal, timeout}
+ | {error, atom()}.
-callback init({atom(), http}, Req, opts())
-> {ok, Req, state()}
@@ -54,4 +57,4 @@
| {loop, Req, State}
| {loop, Req, State, hibernate}
when Req::cowboy_req:req(), State::state().
--callback terminate(cowboy_req:req(), state()) -> ok.
+-callback terminate(terminate_reason(), cowboy_req:req(), state()) -> ok.