aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorjdamanalo <[email protected]>2023-03-09 15:54:41 +0800
committerLoïc Hoguin <[email protected]>2023-12-15 15:37:34 +0100
commita81dc8af9db314e074512e7fc096978c64c9bed1 (patch)
tree6baf1b170887c4d3ddeb40d3c3daf98031dc7b34 /src
parenta72bf4105f6751662ff00fed85bbdc22ee9c2b80 (diff)
downloadcowboy-a81dc8af9db314e074512e7fc096978c64c9bed1.tar.gz
cowboy-a81dc8af9db314e074512e7fc096978c64c9bed1.tar.bz2
cowboy-a81dc8af9db314e074512e7fc096978c64c9bed1.zip
Add timeout to cowboy_loop
LH: I have added a test that does both hibernate and timeout and fixed a related issue. I also tweaked the docs and tests.
Diffstat (limited to 'src')
-rw-r--r--src/cowboy_loop.erl43
1 files changed, 26 insertions, 17 deletions
diff --git a/src/cowboy_loop.erl b/src/cowboy_loop.erl
index 21eb96e..9d070db 100644
--- a/src/cowboy_loop.erl
+++ b/src/cowboy_loop.erl
@@ -17,12 +17,15 @@
-export([upgrade/4]).
-export([upgrade/5]).
--export([loop/4]).
+-export([loop/5]).
-export([system_continue/3]).
-export([system_terminate/4]).
-export([system_code_change/4]).
+%% From gen_server.
+-define(is_timeout(X), ((X) =:= infinity orelse (is_integer(X) andalso (X) >= 0))).
+
-callback init(Req, any())
-> {ok | module(), Req, any()}
| {module(), Req, any(), any()}
@@ -41,40 +44,46 @@
-> {ok, Req, Env} | {suspend, ?MODULE, loop, [any()]}
when Req::cowboy_req:req(), Env::cowboy_middleware:env().
upgrade(Req, Env, Handler, HandlerState) ->
- loop(Req, Env, Handler, HandlerState).
+ loop(Req, Env, Handler, HandlerState, infinity).
--spec upgrade(Req, Env, module(), any(), hibernate)
+-spec upgrade(Req, Env, module(), any(), hibernate | timeout())
-> {suspend, ?MODULE, loop, [any()]}
when Req::cowboy_req:req(), Env::cowboy_middleware:env().
upgrade(Req, Env, Handler, HandlerState, hibernate) ->
- suspend(Req, Env, Handler, HandlerState).
+ suspend(Req, Env, Handler, HandlerState);
+upgrade(Req, Env, Handler, HandlerState, Timeout) when ?is_timeout(Timeout) ->
+ loop(Req, Env, Handler, HandlerState, Timeout).
--spec loop(Req, Env, module(), any())
+-spec loop(Req, Env, module(), any(), timeout())
-> {ok, Req, Env} | {suspend, ?MODULE, loop, [any()]}
when Req::cowboy_req:req(), Env::cowboy_middleware:env().
%% @todo Handle system messages.
-loop(Req=#{pid := Parent}, Env, Handler, HandlerState) ->
+loop(Req=#{pid := Parent}, Env, Handler, HandlerState, Timeout) ->
receive
%% System messages.
{'EXIT', Parent, Reason} ->
terminate(Req, Env, Handler, HandlerState, Reason);
{system, From, Request} ->
sys:handle_system_msg(Request, From, Parent, ?MODULE, [],
- {Req, Env, Handler, HandlerState});
+ {Req, Env, Handler, HandlerState, Timeout});
%% Calls from supervisor module.
{'$gen_call', From, Call} ->
cowboy_children:handle_supervisor_call(Call, From, [], ?MODULE),
- loop(Req, Env, Handler, HandlerState);
+ loop(Req, Env, Handler, HandlerState, Timeout);
Message ->
- call(Req, Env, Handler, HandlerState, Message)
+ call(Req, Env, Handler, HandlerState, Timeout, Message)
+ after Timeout ->
+ call(Req, Env, Handler, HandlerState, Timeout, timeout)
end.
-call(Req0, Env, Handler, HandlerState0, Message) ->
+call(Req0, Env, Handler, HandlerState0, Timeout, Message) ->
try Handler:info(Message, Req0, HandlerState0) of
{ok, Req, HandlerState} ->
- loop(Req, Env, Handler, HandlerState);
+ loop(Req, Env, Handler, HandlerState, Timeout);
{ok, Req, HandlerState, hibernate} ->
suspend(Req, Env, Handler, HandlerState);
+ {ok, Req, HandlerState, NewTimeout} when ?is_timeout(NewTimeout) ->
+ loop(Req, Env, Handler, HandlerState, NewTimeout);
{stop, Req, HandlerState} ->
terminate(Req, Env, Handler, HandlerState, stop)
catch Class:Reason:Stacktrace ->
@@ -83,7 +92,7 @@ call(Req0, Env, Handler, HandlerState0, Message) ->
end.
suspend(Req, Env, Handler, HandlerState) ->
- {suspend, ?MODULE, loop, [Req, Env, Handler, HandlerState]}.
+ {suspend, ?MODULE, loop, [Req, Env, Handler, HandlerState, infinity]}.
terminate(Req, Env, Handler, HandlerState, Reason) ->
Result = cowboy_handler:terminate(Reason, Req, HandlerState, Handler),
@@ -91,15 +100,15 @@ terminate(Req, Env, Handler, HandlerState, Reason) ->
%% System callbacks.
--spec system_continue(_, _, {Req, Env, module(), any()})
+-spec system_continue(_, _, {Req, Env, module(), any(), timeout()})
-> {ok, Req, Env} | {suspend, ?MODULE, loop, [any()]}
when Req::cowboy_req:req(), Env::cowboy_middleware:env().
-system_continue(_, _, {Req, Env, Handler, HandlerState}) ->
- loop(Req, Env, Handler, HandlerState).
+system_continue(_, _, {Req, Env, Handler, HandlerState, Timeout}) ->
+ loop(Req, Env, Handler, HandlerState, Timeout).
--spec system_terminate(any(), _, _, {Req, Env, module(), any()})
+-spec system_terminate(any(), _, _, {Req, Env, module(), any(), timeout()})
-> {ok, Req, Env} when Req::cowboy_req:req(), Env::cowboy_middleware:env().
-system_terminate(Reason, _, _, {Req, Env, Handler, HandlerState}) ->
+system_terminate(Reason, _, _, {Req, Env, Handler, HandlerState, _}) ->
terminate(Req, Env, Handler, HandlerState, Reason).
-spec system_code_change(Misc, _, _, _) -> {ok, Misc}