summaryrefslogtreecommitdiff
path: root/erts/emulator/test/bif_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/test/bif_SUITE.erl')
-rw-r--r--erts/emulator/test/bif_SUITE.erl50
1 files changed, 49 insertions, 1 deletions
diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl
index 6a6e0930bd..5923038eb6 100644
--- a/erts/emulator/test/bif_SUITE.erl
+++ b/erts/emulator/test/bif_SUITE.erl
@@ -39,6 +39,7 @@
is_process_alive/1,
process_info_blast/1,
os_env_case_sensitivity/1,
+ verify_middle_queue_save/1,
test_length/1,
fixed_apply_badarg/1,
external_fun_apply3/1]).
@@ -57,7 +58,8 @@ all() ->
error_stacktrace, error_stacktrace_during_call_trace,
group_leader_prio, group_leader_prio_dirty,
is_process_alive, process_info_blast, os_env_case_sensitivity,
- test_length,fixed_apply_badarg,external_fun_apply3].
+ verify_middle_queue_save, test_length,fixed_apply_badarg,
+ external_fun_apply3].
init_per_testcase(guard_bifs_in_erl_bif_types, Config) when is_list(Config) ->
skip_missing_erl_bif_types(Config);
@@ -1277,6 +1279,52 @@ consume_msgs() ->
ok
end.
+
+%% Test that process_info(Pid, [message_queue_len]) works correctly when
+%% fetching part of the middle signal queue into inner queue.
+verify_middle_queue_save(Config) when is_list(Config) ->
+ Control = self(),
+ ProcessToHang = spawn_link(
+ fun () ->
+ Single = self(),
+ put(count, 0),
+ Doubles = [spawn_link(fun () -> message_queue_len_retrievers(Single, 0) end) || _ <- lists:seq(1, 2)],
+ Control ! {doubles, Doubles},
+ process_that_hangs(Control, 0, Doubles)
+ end),
+ ensure_not_hanging(ProcessToHang, [], 50000).
+
+process_that_hangs(Control, Total, Doubles) ->
+ put(count, Total),
+ %% fetch something innocent, like 'priority' of the process
+ [process_info(Pid, [priority]) || Pid <- Doubles],
+ Control ! alive,
+ process_that_hangs(Control, Total + 1, Doubles).
+
+message_queue_len_retrievers(Control, PrevCount) ->
+ %% need to fetch dictionary for test reasons, but actual trigger is 'message_queue_len',
+ %% or 'memory', or 'total_heap_size' - anything that needs to fetch external message queue
+ %% via ERTS_PI_FLAG_NEED_MSGQ_LEN internal flag to process_info
+ [_, {dictionary, [{count, Count}]}] = erlang:process_info(Control, [message_queue_len, dictionary]),
+ Count > PrevCount andalso begin Control ! count end,
+ message_queue_len_retrievers(Control, Count).
+
+ensure_not_hanging(Proc, _Doubles, 0) ->
+ unlink(Proc),
+ exit(Proc, kill);
+ensure_not_hanging(Proc, Doubles, Remaining) ->
+ receive
+ alive ->
+ ensure_not_hanging(Proc, Doubles, Remaining - 1);
+ {doubles, NewDoubles} ->
+ ensure_not_hanging(Proc, NewDoubles, Remaining)
+ after 1000 ->
+ Reason = {Proc, "hung", erlang:process_info(Proc, backtrace)},
+ unlink(Proc),
+ exit(Proc, kill),
+ ct:fail(Reason)
+ end.
+
%% Test that length/1 returns the correct result after trapping, and
%% also that the argument is correct in the stacktrace for a badarg
%% exception.