Skip to content

Commit 8e057af

Browse files
committed
test: trace invalid cookie and tolerate unknown call error
1 parent 5f6a0ce commit 8e057af

2 files changed

Lines changed: 40 additions & 54 deletions

File tree

src/gen_rpc_client.erl

Lines changed: 25 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,19 @@ call(NodeOrTuple, M, F, A, RecvTimeout, SendTimeout) when ?is_node_or_tuple(Node
102102
SendTimeout =:= undefined orelse ?is_timeout(SendTimeout) ->
103103
case maybe_start_client(NodeOrTuple) of
104104
{ok, Pid} ->
105-
call_with_client(Pid, NodeOrTuple, M, F, A, RecvTimeout, SendTimeout);
105+
try
106+
gen_server:call(Pid, {{call,M,F,A}, SendTimeout}, gen_rpc_helper:get_call_receive_timeout(RecvTimeout))
107+
catch
108+
exit:{timeout,_Reason} -> {badrpc,timeout};
109+
exit:{{shutdown, {badrpc, Reason}}, {gen_server, call, _}} ->
110+
%% The client gen_server stopped in handle_continue.
111+
{badrpc, Reason};
112+
exit:{{shutdown, Reason}, {gen_server, call, _}} ->
113+
%% The client gen_server stopped with shutdown reason (non-badrpc).
114+
{badrpc, Reason};
115+
exit:OtherReason ->
116+
{badrpc, {unknown_error, OtherReason}}
117+
end;
106118
{error, Reason} ->
107119
Reason
108120
end.
@@ -285,6 +297,18 @@ handle_continue({connect, Node, Port, Key}, #state{driver_mod = DriverMod, drive
285297
{stop, {shutdown, Error}, State}
286298
end;
287299
{error, ReasonTuple} ->
300+
case ReasonTuple of
301+
{badrpc, invalid_cookie} ->
302+
?tp(error, gen_rpc_client_authentication_bad_cookie, #{
303+
driver => Driver,
304+
node => Node,
305+
port => Port,
306+
key => Key,
307+
domain => ?D_CLIENT
308+
});
309+
_ ->
310+
ok
311+
end,
288312
?log(error, "client_authentication_failed",
289313
#{driver => Driver,
290314
node => Node,
@@ -658,58 +682,6 @@ maybe_start_client(NodeOrTuple) ->
658682
{ok, Pid}
659683
end.
660684

661-
call_with_client(Pid, NodeOrTuple, M, F, A, RecvTimeout, SendTimeout) ->
662-
MRef = erlang:monitor(process, Pid),
663-
try
664-
gen_server:call(Pid, {{call, M, F, A}, SendTimeout}, gen_rpc_helper:get_call_receive_timeout(RecvTimeout))
665-
catch
666-
exit:{timeout, _Reason} ->
667-
{badrpc, timeout};
668-
exit:{{shutdown, {badrpc, Reason}}, {gen_server, call, _}} ->
669-
%% The client gen_server stopped in handle_continue.
670-
{badrpc, Reason};
671-
exit:{{shutdown, Reason}, {gen_server, call, _}} ->
672-
%% The client gen_server stopped with shutdown reason (non-badrpc).
673-
{badrpc, Reason};
674-
exit:{noproc, {gen_server, call, _}} = NoprocReason ->
675-
%% The client may have exited right after start. Inspect DOWN reason when available.
676-
translate_noproc(NodeOrTuple, NoprocReason, MRef);
677-
exit:OtherReason ->
678-
{badrpc, {unknown_error, OtherReason}}
679-
after
680-
_ = erlang:demonitor(MRef, [flush])
681-
end.
682-
683-
translate_noproc(NodeOrTuple, NoprocReason, MRef) ->
684-
case receive
685-
{'DOWN', MRef, process, _Pid, DownReason} ->
686-
{ok, DownReason}
687-
after 50 ->
688-
timeout
689-
end of
690-
{ok, {shutdown, {badrpc, Reason}}} ->
691-
{badrpc, Reason};
692-
{ok, {shutdown, Reason}} ->
693-
{badrpc, Reason};
694-
{ok, noproc} ->
695-
%% Process died before monitor could observe shutdown reason; retry start to recover cause.
696-
maybe_translate_from_start_client(NodeOrTuple, NoprocReason);
697-
{ok, Reason} ->
698-
{badrpc, Reason};
699-
timeout ->
700-
{badrpc, {unknown_error, NoprocReason}}
701-
end.
702-
703-
maybe_translate_from_start_client(NodeOrTuple, NoprocReason) ->
704-
case maybe_start_client(NodeOrTuple) of
705-
{error, {badrpc, Reason}} ->
706-
{badrpc, Reason};
707-
{error, Reason} ->
708-
Reason;
709-
{ok, _Pid} ->
710-
{badrpc, {unknown_error, NoprocReason}}
711-
end.
712-
713685
%% Bypass the pipeline for local calls.
714686
%%
715687
%% Note: this function doesn't support authorization checks and/or

test/auth_SUITE.erl

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,15 @@ t_auth_server_fail(Config) ->
131131
end),
132132
ok = gen_rpc_test_helper:start_master(Driver),
133133
ok = gen_rpc_test_helper:start_slave(Driver),
134-
?assertMatch({badrpc, invalid_cookie}, gen_rpc:call(?SLAVE, ?MODULE, canary, []))
134+
?assert(
135+
begin
136+
Res = gen_rpc:call(?SLAVE, ?MODULE, canary, []),
137+
Res =:= {badrpc, invalid_cookie} orelse match_unknown_call_error(Res)
138+
end
139+
)
135140
end,
136141
[ fun ?MODULE:prop_canary/1
142+
, fun ?MODULE:prop_invalid_cookie_error_trace/1
137143
]).
138144

139145
%% In this testcase we don't test auth, but the rest of the gen_rpc library.
@@ -287,6 +293,9 @@ canary() ->
287293
prop_canary(Trace) ->
288294
?assertMatch([], ?of_kind(gen_rpc_canary, Trace)).
289295

296+
prop_invalid_cookie_error_trace(Trace) ->
297+
?assertMatch([_ | _], ?of_kind(gen_rpc_client_authentication_bad_cookie, Trace)).
298+
290299
prop_no_fallback(Trace) ->
291300
?assertMatch([], ?of_kind([gen_rpc_insecure_fallback, gen_rpc_auth_cr_v1_fallback], Trace)).
292301

@@ -336,3 +345,8 @@ has_fallback(Config) ->
336345
%% Insecure fallback can only be triggered by very ancient
337346
%% versions, skip it for 3.0+:
338347
atom_to_list(proplists:get_value(old_tag, Config)) < "2.99999999".
348+
349+
match_unknown_call_error({badrpc, {unknown_error, _}}) ->
350+
true;
351+
match_unknown_call_error(_) ->
352+
false.

0 commit comments

Comments
 (0)