diff options
| author | Luke Bakken <lbakken@pivotal.io> | 2018-12-06 10:04:34 -0800 |
|---|---|---|
| committer | Luke Bakken <lbakken@pivotal.io> | 2018-12-06 10:04:34 -0800 |
| commit | 61e33f6e15878d8742b53ee7e256548e31203c75 (patch) | |
| tree | 7bcae8ae50cd969650a9ddd4c480582be72f0612 | |
| parent | 19f3901df38384f626c2d355a8c4e6ad216ef6e3 (diff) | |
| download | rabbitmq-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.erl | 63 |
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}. |
