diff options
Diffstat (limited to 'erts/emulator/test/process_SUITE.erl')
-rw-r--r-- | erts/emulator/test/process_SUITE.erl | 228 |
1 files changed, 142 insertions, 86 deletions
diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index 080b63c5f6..d28c4d15db 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -95,10 +95,10 @@ alias_bif/1, monitor_alias/1, spawn_monitor_alias/1, - alias_process_exit/1, demonitor_aliasmonitor/1, down_aliasmonitor/1, - monitor_tag/1]). + monitor_tag/1, + no_pid_wrap/1]). -export([prio_server/2, prio_client/2, init/1, handle_event/2]). @@ -131,7 +131,8 @@ all() -> {group, otp_7738}, garb_other_running, {group, system_task}, {group, alias}, - monitor_tag]. + monitor_tag, + no_pid_wrap]. groups() -> [{t_exit_2, [], @@ -185,7 +186,7 @@ groups() -> gc_request_when_gc_disabled, gc_request_blast_when_gc_disabled, otp_16436, otp_16642]}, {alias, [], - [alias_bif, monitor_alias, spawn_monitor_alias, alias_process_exit, + [alias_bif, monitor_alias, spawn_monitor_alias, demonitor_aliasmonitor, down_aliasmonitor]}]. init_per_suite(Config) -> @@ -205,15 +206,9 @@ end_per_suite(Config) -> catch erts_debug:set_internal_state(available_internal_state, false), Config. -init_per_group(alias, Config) -> - erts_debug:set_internal_state(available_internal_state, true), - Config; init_per_group(_GroupName, Config) -> Config. -end_per_group(alias, Config) -> - erts_debug:set_internal_state(available_internal_state, false), - Config; end_per_group(_GroupName, Config) -> Config. @@ -234,6 +229,7 @@ end_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> erlang:system_flag(max_heap_size, #{size => 0, kill => true, + include_shared_binaries => false, error_logger => true}), erts_test_utils:ept_check_leaked_nodes(Config). @@ -539,7 +535,8 @@ t_process_info(Config) when is_list(Config) -> {status, running} = process_info(self(), status), {min_heap_size, 233} = process_info(self(), min_heap_size), {min_bin_vheap_size,46422} = process_info(self(), min_bin_vheap_size), - {max_heap_size, #{ size := 0, kill := true, error_logger := true}} = + {max_heap_size, #{ size := 0, kill := true, error_logger := true, + include_shared_binaries := false}} = process_info(self(), max_heap_size), {current_function,{?MODULE,t_process_info,1}} = process_info(self(), current_function), @@ -697,8 +694,9 @@ process_info_other_msg(Config) when is_list(Config) -> {min_heap_size, 233} = process_info(Pid, min_heap_size), {min_bin_vheap_size, 46422} = process_info(Pid, min_bin_vheap_size), - {max_heap_size, #{ size := 0, kill := true, error_logger := true}} = - process_info(self(), max_heap_size), + {max_heap_size, #{ size := 0, kill := true, error_logger := true, + include_shared_binaries := false}} = + process_info(Pid, max_heap_size), Pid ! stop, ok. @@ -1089,6 +1087,20 @@ check_proc_infos(A, B) -> GC = lists:keysearch(garbage_collection, 1, A), GC = lists:keysearch(garbage_collection, 1, B), + {value, {garbage_collection, GClist}} = GC, + + %% This is not really documented + true = is_integer(gv(minor_gcs, GClist)), + true = is_integer(gv(fullsweep_after, GClist)), + true = is_integer(gv(min_heap_size, GClist)), + #{error_logger := Bool1, + include_shared_binaries := Bool2, + kill := Bool3, + size := MaxHeapSize} = gv(max_heap_size, GClist), + true = is_boolean(Bool1), + true = is_boolean(Bool2), + true = is_boolean(Bool3), + true = is_integer(MaxHeapSize), ok. @@ -1956,6 +1968,8 @@ process_flag_badarg(Config) when is_list(Config) -> chk_badarg(fun () -> process_flag(max_heap_size, #{ size => 233, error_logger => gurka }) end), chk_badarg(fun () -> process_flag(max_heap_size, #{ size => 233, + include_shared_binaries => gurka}) end), + chk_badarg(fun () -> process_flag(max_heap_size, #{ size => 233, kill => true, error_logger => gurka }) end), chk_badarg(fun () -> process_flag(max_heap_size, #{ size => 1 bsl 64 }) end), @@ -2605,63 +2619,72 @@ spawn_opt_max_heap_size(_Config) -> flush() end, + spawn_opt_max_heap_size_do(fun oom_fun/1), + + io:format("Repeat tests with refc binaries\n",[]), + + spawn_opt_max_heap_size_do(fun oom_bin_fun/1), + + error_logger:delete_report_handler(?MODULE), + ok. + +spawn_opt_max_heap_size_do(OomFun) -> + Max = 2024, %% Test that numerical limit works - max_heap_size_test(1024, 1024, true, true), + max_heap_size_test(Max, Max, true, true, OomFun), %% Test that map limit works - max_heap_size_test(#{ size => 1024 }, 1024, true, true), + max_heap_size_test(#{ size => Max }, Max, true, true, OomFun), %% Test that no kill is sent - max_heap_size_test(#{ size => 1024, kill => false }, 1024, false, true), + max_heap_size_test(#{ size => Max, kill => false }, Max, false, true, OomFun), %% Test that no error_logger report is sent - max_heap_size_test(#{ size => 1024, error_logger => false }, 1024, true, false), + max_heap_size_test(#{ size => Max, error_logger => false }, Max, true, false, OomFun), %% Test that system_flag works - erlang:system_flag(max_heap_size, #{ size => 0, kill => false, - error_logger => true}), - max_heap_size_test(#{ size => 1024 }, 1024, false, true), - max_heap_size_test(#{ size => 1024, kill => true }, 1024, true, true), + erlang:system_flag(max_heap_size, OomFun(#{ size => 0, kill => false, + error_logger => true})), + max_heap_size_test(#{ size => Max }, Max, false, true, OomFun), + max_heap_size_test(#{ size => Max, kill => true }, Max, true, true, OomFun), - erlang:system_flag(max_heap_size, #{ size => 0, kill => true, - error_logger => false}), - max_heap_size_test(#{ size => 1024 }, 1024, true, false), - max_heap_size_test(#{ size => 1024, error_logger => true }, 1024, true, true), + erlang:system_flag(max_heap_size, OomFun(#{ size => 0, kill => true, + error_logger => false})), + max_heap_size_test(#{ size => Max }, Max, true, false, OomFun), + max_heap_size_test(#{ size => Max, error_logger => true }, Max, true, true, OomFun), - erlang:system_flag(max_heap_size, #{ size => 1 bsl 20, kill => true, - error_logger => true}), - max_heap_size_test(#{ }, 1 bsl 20, true, true), + erlang:system_flag(max_heap_size, OomFun(#{ size => 1 bsl 16, kill => true, + error_logger => true})), + max_heap_size_test(#{ }, 1 bsl 16, true, true, OomFun), erlang:system_flag(max_heap_size, #{ size => 0, kill => true, error_logger => true}), %% Test that ordinary case works as expected again - max_heap_size_test(1024, 1024, true, true), + max_heap_size_test(Max, Max, true, true, OomFun), + ok. - error_logger:delete_report_handler(?MODULE), - ok. +mhs_spawn_opt(Option) when map_get(size, Option) > 0; + is_integer(Option) -> + [{max_heap_size, Option}]; +mhs_spawn_opt(_) -> + []. -max_heap_size_test(Option, Size, Kill, ErrorLogger) - when map_size(Option) == 0 -> - max_heap_size_test([], Size, Kill, ErrorLogger); -max_heap_size_test(Option, Size, Kill, ErrorLogger) - when is_map(Option); is_integer(Option) -> - max_heap_size_test([{max_heap_size, Option}], Size, Kill, ErrorLogger); -max_heap_size_test(Option, Size, Kill, ErrorLogger) -> - OomFun = fun () -> oom_fun([]) end, - Pid = spawn_opt(OomFun, Option), +max_heap_size_test(Option, Size, Kill, ErrorLogger, OomFun) -> + SpOpt = mhs_spawn_opt(OomFun(Option)), + Pid = spawn_opt(fun()-> OomFun(run) end, SpOpt), {max_heap_size, MHSz} = erlang:process_info(Pid, max_heap_size), - ct:log("Default: ~p~nOption: ~p~nProc: ~p~n", - [erlang:system_info(max_heap_size), Option, MHSz]), + ct:log("Default: ~p~nOption: ~p~nProc: ~p~nSize = ~p~nSpOpt = ~p~n", + [erlang:system_info(max_heap_size), Option, MHSz, Size, SpOpt]), #{ size := Size} = MHSz, Ref = erlang:monitor(process, Pid), if Kill -> receive - {'DOWN', Ref, process, Pid, killed} -> - ok + {'DOWN', Ref, process, Pid, Reason} -> + killed = Reason end; true -> ok @@ -2692,12 +2715,37 @@ max_heap_size_test(Option, Size, Kill, ErrorLogger) -> %% Make sure that there are no unexpected messages. receive_unexpected(). -oom_fun(Acc0) -> +oom_fun(Max) when is_integer(Max) -> Max; +oom_fun(Map) when is_map(Map)-> Map; +oom_fun(run) -> + io:format("oom_fun() started\n",[]), + oom_run_fun([], 100). + +oom_run_fun(Acc0, 0) -> + done; +oom_run_fun(Acc0, N) -> %% This is tail-recursive since the compiler is smart enough to figure %% out that a body-recursive variant never returns, and loops forever %% without keeping the list alive. timer:sleep(5), - oom_fun([lists:seq(1, 1000) | Acc0]). + oom_run_fun([lists:seq(1, 1000) | Acc0], N-1). + +oom_bin_fun(Max) when is_integer(Max) -> oom_bin_fun(#{size => Max}); +oom_bin_fun(Map) when is_map(Map) -> Map#{include_shared_binaries => true}; +oom_bin_fun(run) -> + oom_bin_run_fun([], 10). + +oom_bin_run_fun(Acc0, 0) -> + done; +oom_bin_run_fun(Acc0, N) -> + timer:sleep(5), + oom_bin_run_fun([build_refc_bin(160, <<>>) | Acc0], N-1). + +build_refc_bin(0, Acc) -> + Acc; +build_refc_bin(N, Acc) -> + build_refc_bin(N-1, <<Acc/binary, 0:(1000*8)>>). + receive_error_messages(Pid) -> receive @@ -4692,25 +4740,11 @@ otp_16642(Config) when is_list(Config) -> false = is_process_alive(Pid), ok. -pid_ref_table_size() -> - erts_debug:get_internal_state(pid_ref_table_size). - -check_pid_ref_table_size(PRTSz) -> - receive after 500 -> ok end, - case pid_ref_table_size() of - PRTSz -> - ok; - NewPRTSz -> - ct:fail({port_ref_table_size_mismatch, PRTSz, NewPRTSz}) - end. - alias_bif(Config) when is_list(Config) -> - PRTSz = pid_ref_table_size(), alias_bif_test(node()), {ok, Peer, Node} = ?CT_PEER(), alias_bif_test(Node), stop_node(Peer, Node), - check_pid_ref_table_size(PRTSz), ok. alias_bif_test(Node) -> @@ -4755,12 +4789,10 @@ alias_bif_test(Node) -> monitor_alias(Config) when is_list(Config) -> - PRTSz = pid_ref_table_size(), monitor_alias_test(node()), {ok, Peer, Node} = ?CT_PEER(), monitor_alias_test(Node), stop_node(Peer, Node), - check_pid_ref_table_size(PRTSz), ok. monitor_alias_test(Node) -> @@ -4844,7 +4876,6 @@ monitor_alias_test(Node) -> spawn_monitor_alias(Config) when is_list(Config) -> %% Exit signals with immediate exit reasons are sent %% in a different manner than compound exit reasons. - PRTSz = pid_ref_table_size(), spawn_monitor_alias_test(undefined, node(), spawn_opt, normal), spawn_monitor_alias_test(undefined, node(), spawn_opt, make_ref()), spawn_monitor_alias_test(undefined, node(), spawn_request, normal), @@ -4857,7 +4888,6 @@ spawn_monitor_alias(Config) when is_list(Config) -> spawn_monitor_alias_test(Peer3, Node3, spawn_request, normal), {ok, Peer4, Node4} = ?CT_PEER(), spawn_monitor_alias_test(Peer4, Node4, spawn_request, make_ref()), - check_pid_ref_table_size(PRTSz), ok. spawn_monitor_alias_test(Peer, Node, SpawnType, ExitReason) -> @@ -4998,28 +5028,6 @@ spawn_monitor_alias_test(Peer, Node, SpawnType, ExitReason) -> ok end. -alias_process_exit(Config) when is_list(Config) -> - Tester = self(), - CreatedAliases = make_ref(), - PRTSz = pid_ref_table_size(), - P = spawn_link(fun () -> - A0 = alias([explicit_unalias]), - A1 = alias([reply]), - A2 = monitor(process, Tester, [{alias, explicit_unalias}]), - A3 = monitor(process, Tester, [{alias, demonitor}]), - A4 = monitor(process, Tester, [{alias, reply_demonitor}]), - Tester ! CreatedAliases, - receive after infinity -> ok end, - some_module:some_function([A0, A1, A2, A3, A4]) - end), - receive CreatedAliases -> ok end, - PRTSz = erts_debug:get_internal_state(pid_ref_table_size) - 5, - unlink(P), - exit(P, kill), - false = is_process_alive(P), - check_pid_ref_table_size(PRTSz), - ok. - demonitor_aliasmonitor(Config) when is_list(Config) -> {ok, Peer, Node} = ?CT_PEER(), Fun = fun () -> @@ -5156,6 +5164,54 @@ monitor_tag_test(Peer, Node, SpawnType, Tag, ExitReason) -> ok end. +no_pid_wrap(Config) when is_list(Config) -> + process_flag(priority, high), + SOnln = erlang:system_info(schedulers_online), + Pid = spawn(fun () -> ok end), + exit(Pid, kill), + false = is_process_alive(Pid), + ChkSpwndPid = fun () -> + check_spawned_pid(Pid) + end, + MPs = maps:from_list(lists:map(fun (_) -> + {P, M} = spawn_monitor(ChkSpwndPid), + {M, P} + end, lists:seq(1, SOnln))), + Res = receive + {'DOWN', M, process, _, pid_reused} when is_map_key(M, MPs) -> + case erlang:system_info(wordsize) of + 8 -> + ct:fail("Process identifier reused"), + error; + 4 -> + {comment, + "Process identifer reused, but this is" + ++ "expected since this is a 32-bit system"} + end; + {'DOWN', _, _, _, _} = Down -> + ct:fail({unexpected_down, Down}), + error + after + 3*60*1000 -> + ok + end, + maps:foreach(fun (_, P) -> + exit(P, kill) + end, MPs), + maps:foreach(fun (_, P) -> + false = is_process_alive(P) + end, MPs), + Res. + +check_spawned_pid(OldPid) -> + Pid = spawn(fun () -> ok end), + case OldPid == Pid of + false -> + check_spawned_pid(OldPid); + true -> + exit(pid_reused) + end. + %% Internal functions recv_msgs(N) -> |