diff options
| author | Rickard Green <rickard@erlang.org> | 2023-04-29 00:30:12 +0200 |
|---|---|---|
| committer | Rickard Green <rickard@erlang.org> | 2023-04-29 00:59:16 +0200 |
| commit | 330b119be68f95f6f8fbdef8bf16bba314783973 (patch) | |
| tree | f78d545d1f7f2ff98410150028981f14e9f527b5 /erts/emulator/test | |
| parent | 3002f55f409f44122d3a45ac53bfd453e9aa2cb2 (diff) | |
| download | erlang-330b119be68f95f6f8fbdef8bf16bba314783973.tar.gz | |
[erts] ensure no mix of external and internal identifiers
Silently reject proposed creation and select another one when a node goes
alive if there are external identifiers in the system with the proposed
creation and the same node name that are to be used. Such identifiers would
not work as expected in various situations, and are not from the instance of
the node that are about to go alive.
Diffstat (limited to 'erts/emulator/test')
| -rw-r--r-- | erts/emulator/test/distribution_SUITE.erl | 123 |
1 files changed, 121 insertions, 2 deletions
diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl index 128c9b07e0..61d9ced3b5 100644 --- a/erts/emulator/test/distribution_SUITE.erl +++ b/erts/emulator/test/distribution_SUITE.erl @@ -75,7 +75,9 @@ system_limit/1, hopefull_data_encoding/1, hopefull_export_fun_bug/1, - huge_iovec/1]). + huge_iovec/1, + creation_selection/1, + creation_selection_test/1]). %% Internal exports. -export([sender/3, receiver2/2, dummy_waiter/0, dead_process/0, @@ -106,7 +108,7 @@ all() -> {group, bad_dist}, {group, bad_dist_ext}, start_epmd_false, epmd_module, system_limit, hopefull_data_encoding, hopefull_export_fun_bug, - huge_iovec]. + huge_iovec, creation_selection]. groups() -> [{bulk_send, [], [bulk_send_small, bulk_send_big, bulk_send_bigbig]}, @@ -2810,9 +2812,126 @@ mk_rand_bin(0, Data) -> mk_rand_bin(N, Data) -> mk_rand_bin(N-1, [rand:uniform(256) - 1 | Data]). +creation_selection(Config) when is_list(Config) -> + register(creation_selection_test_supervisor, self()), + Name = atom_to_list(?FUNCTION_NAME) ++ "-" + ++ integer_to_list(erlang:system_time()), + Host = hostname(), + Cmd = lists:append( + [ct:get_progname(), + " -noshell", + " -setcookie ", atom_to_list(erlang:get_cookie()), + " -pa ", filename:dirname(code:which(?MODULE)), + " -s ", atom_to_list(?MODULE), " ", + " creation_selection_test ", atom_to_list(node()), " ", + atom_to_list(net_kernel:longnames()), " ", Name, " ", Host]), + ct:pal("Node command: ~p~n", [Cmd]), + Port = open_port({spawn, Cmd}, [exit_status]), + Node = list_to_atom(lists:append([Name, "@", Host])), + ok = receive_creation_selection_info(Port, Node). + +receive_creation_selection_info(Port, Node) -> + receive + {creation_selection_test, Node, Creations, InvalidCreation, + ClashResolvedCreation} = Msg -> + ct:log("Test result: ~p~n", [Msg]), + %% Verify that creation values are created as expected. The + %% list of creations is in reverse start order... + MaxC = (1 bsl 32) - 1, + MinC = 4, + StartOrderCreations = lists:reverse(Creations), + InvalidCreation = lists:foldl(fun (C, C) when is_integer(C), + MinC =< C, + C =< MaxC -> + %% Return next expected + %% creation... + if C == MaxC -> MinC; + true -> C+1 + end + end, + hd(StartOrderCreations), + StartOrderCreations), + false = lists:member(ClashResolvedCreation, [InvalidCreation + | Creations]), + receive + {Port, {exit_status, 0}} -> + Port ! {self(), close}, + ok; + {Port, {exit_status, EStat}} -> + ct:fail({"node exited abnormally: ", EStat}) + end; + {Port, {exit_status, EStat}} -> + ct:fail({"node prematurely exited: ", EStat}); + {Port, {data, Data}} -> + ct:log("~ts", [Data]), + receive_creation_selection_info(Port, Node) + end, + ok. + +creation_selection_test([TestSupNode, LongNames, Name, Host]) -> + try + StartArgs = [Name, + case LongNames of + true -> longnames; + false -> shortnames + end], + Node = list_to_atom(lists:append([atom_to_list(Name), + "@", atom_to_list(Host)])), + GoDistributed = fun (F) -> + {ok, _} = net_kernel:start(StartArgs), + Node = node(), + Creation = erlang:system_info(creation), + _ = F(Creation), + net_kernel:stop(), + Creation + end, + %% We start multiple times to verify that the creation values + %% we get from epmd are delivered in sequence. This is a + %% must for the test case such as it is written now, but can be + %% changed. If changed, this test case must be updated... + {Creations, + LastCreation} = lists:foldl(fun (_, {Cs, _LC}) -> + CFun = fun (X) -> X end, + C = GoDistributed(CFun), + {[C|Cs], C} + end, {[], 0}, lists:seq(1, 5)), + %% We create a pid with the creation that epmd will offer us the next + %% time we start the distribution and then start the distribution + %% once more. The node should avoid this creation, since this would + %% cause external identifiers in the system with same + %% nodename/creation pair as used by the local node, which in turn + %% would cause these identifers not to work as expected. That is, the + %% node should silently reject this creation and chose another one when + %% starting the distribution. + InvalidCreation = LastCreation+1, + Pid = erts_test_utils:mk_ext_pid({Node, InvalidCreation}, 4711, 0), + true = erts_debug:size(Pid) > 0, %% External pid + ResultFun = fun (ClashResolvedCreation) -> + pong = net_adm:ping(TestSupNode), + Msg = {creation_selection_test, node(), Creations, + InvalidCreation, ClashResolvedCreation}, + {creation_selection_test_supervisor, TestSupNode} + ! Msg, + %% Wait a bit so the message have time to get + %% through before we take down the distribution... + receive after 500 -> ok end + end, + _ = GoDistributed(ResultFun), + %% Ensure Pid is not garbage collected before starting the + %% distribution... + _ = id(Pid), + erlang:halt(0) + catch + Class:Reason:StackTrace -> + erlang:display({Class, Reason, StackTrace}), + erlang:halt(17) + end. %%% Utilities +id(X) -> + X. + timestamp() -> erlang:monotonic_time(millisecond). |
