summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Bakken <lbakken@pivotal.io>2018-12-06 10:04:34 -0800
committerLuke Bakken <lbakken@pivotal.io>2018-12-06 10:04:34 -0800
commit61e33f6e15878d8742b53ee7e256548e31203c75 (patch)
tree7bcae8ae50cd969650a9ddd4c480582be72f0612
parent19f3901df38384f626c2d355a8c4e6ad216ef6e3 (diff)
downloadrabbitmq-server-git-61e33f6e15878d8742b53ee7e256548e31203c75.tar.gz
Add code to enforce deadline when getting channel info items. Standardize return value from info gen_server handler
-rw-r--r--src/rabbit_channel.erl63
1 files changed, 54 insertions, 9 deletions
diff --git a/src/rabbit_channel.erl b/src/rabbit_channel.erl
index e143f8a1a8..937e0a4ba3 100644
--- a/src/rabbit_channel.erl
+++ b/src/rabbit_channel.erl
@@ -340,12 +340,29 @@ list_local() ->
info_keys() -> ?INFO_KEYS.
info(Pid) ->
- gen_server2:call(Pid, info, infinity).
+ {Timeout, Deadline} = get_operation_timeout_and_deadline(),
+ try
+ case gen_server2:call(Pid, {info, Deadline}, Timeout) of
+ {ok, Res} -> Res;
+ {error, Error} -> throw(Error)
+ end
+ catch
+ exit:{timeout, _} ->
+ rabbit_log:error("Timed out getting channel ~p info", [Pid]),
+ throw(timeout)
+ end.
info(Pid, Items) ->
- case gen_server2:call(Pid, {info, Items}, infinity) of
- {ok, Res} -> Res;
- {error, Error} -> throw(Error)
+ {Timeout, Deadline} = get_operation_timeout_and_deadline(),
+ try
+ case gen_server2:call(Pid, {{info, Items}, Deadline}, Timeout) of
+ {ok, Res} -> Res;
+ {error, Error} -> throw(Error)
+ end
+ catch
+ exit:{timeout, _} ->
+ rabbit_log:error("Timed out getting channel ~p info", [Pid]),
+ throw(timeout)
end.
info_all() ->
@@ -494,13 +511,20 @@ prioritise_info(Msg, _Len, _State) ->
handle_call(flush, _From, State) ->
reply(ok, State);
-handle_call(info, _From, State) ->
- reply(infos(?INFO_KEYS, State), State);
+handle_call({info, Deadline}, _From, State) ->
+ try
+ reply({ok, infos(?INFO_KEYS, Deadline, State)}, State)
+ catch
+ Error ->
+ reply({error, Error}, State)
+ end;
-handle_call({info, Items}, _From, State) ->
+handle_call({{info, Items}, Deadline}, _From, State) ->
try
- reply({ok, infos(Items, State)}, State)
- catch Error -> reply({error, Error}, State)
+ reply({ok, infos(Items, Deadline, State)}, State)
+ catch
+ Error ->
+ reply({error, Error}, State)
end;
handle_call(refresh_config, _From, State = #ch{virtual_host = VHost}) ->
@@ -2135,6 +2159,17 @@ complete_tx(State = #ch{tx = failed}) ->
infos(Items, State) -> [{Item, i(Item, State)} || Item <- Items].
+infos(Items, Deadline, State) ->
+ [begin
+ Now = now_millis(),
+ if
+ Now > Deadline ->
+ throw(timeout);
+ true ->
+ {Item, i(Item, State)}
+ end
+ end || Item <- Items].
+
i(pid, _) -> self();
i(connection, #ch{conn_pid = ConnPid}) -> ConnPid;
i(number, #ch{channel = Channel}) -> Channel;
@@ -2503,3 +2538,13 @@ qpid_to_ref(Pid) when is_pid(Pid) -> Pid;
qpid_to_ref({Name, _}) -> Name;
%% assume it already is a ref
qpid_to_ref(Ref) -> Ref.
+
+now_millis() ->
+ erlang:monotonic_time(millisecond).
+
+get_operation_timeout_and_deadline() ->
+ % NB: can't use get_operation_timeout because
+ % this code may not be running via the channel Pid
+ Timeout = ?CHANNEL_OPERATION_TIMEOUT,
+ Deadline = now_millis() + Timeout,
+ {Timeout, Deadline}.