summaryrefslogtreecommitdiff
path: root/erts/emulator/test/process_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/test/process_SUITE.erl')
-rw-r--r--erts/emulator/test/process_SUITE.erl228
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) ->