From 4fb4d6c57a987f58915f21af5a6321c5228b45dc Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 21 Jun 2016 19:07:23 +0200 Subject: erts: Add test port_SUITE:pipe_limit_env for 9f779819f6bda734c595. --- erts/emulator/test/port_SUITE.erl | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index ee07699884..c9901ba610 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -91,6 +91,7 @@ exit_status/1, exit_status_multi_scheduling_block/1, huge_env/1, + pipe_limit_env/1, input_only/1, iter_max_ports/1, line/1, @@ -158,6 +159,7 @@ all() -> {group, multiple_packets}, parallell, dying_port, port_program_with_path, open_input_file_port, open_output_file_port, name1, env, huge_env, bad_env, cd, + pipe_limit_env, bad_args, exit_status, iter_max_ports, count_fds, t_exit, {group, tps}, line, stderr_to_stdout, otp_3906, otp_4389, win_massive, @@ -1002,6 +1004,55 @@ huge_env(Config) when is_list(Config) -> ct:fail("Open port failed ~p:~p",[E,R]) end. +%% Test to spawn program with command payload buffer +%% just around pipe capacity (9f779819f6bda734c5953468f7798) +pipe_limit_env(Config) when is_list(Config) -> + Cmd = "true", + CmdSize = command_payload_size(Cmd), + Limits = [4096, 16384, 65536], % Try a couple of common pipe buffer sizes + + lists:foreach(fun(Lim) -> + lists:foreach(fun(L) -> pipe_limit_env_do(L, Cmd, CmdSize) + end, lists:seq(Lim-5, Lim+5)) + end, Limits), + ok. + +pipe_limit_env_do(Bytes, Cmd, CmdSize) -> + case env_of_bytes(Bytes-CmdSize) of + [] -> skip; + Env -> + try erlang:open_port({spawn,Cmd},[exit_status, {env, Env}]) of + P -> + receive + {P, {exit_status,N}} = M -> + %% Bug caused exit_status 150 (EINVAL+128) + 0 = N + end + catch E:R -> + %% Have to catch the error here, as printing the stackdump + %% in the ct log is way to heavy for some test machines. + ct:fail("Open port failed ~p:~p",[E,R]) + end + end. + +%% environ format: KEY=VALUE\0 +env_of_bytes(Bytes) when Bytes > 3 -> + Env = [{"X",lists:duplicate(Bytes-3, $x)}]; +env_of_bytes(_) -> []. + +%% White box assumption about payload written to pipe +%% for Cmd and current environment (see spawn_start in sys_driver.c) +command_payload_size(Cmd) -> + EnvSize = lists:foldl(fun(E,Acc) -> length(E) + 1 + Acc end, + 0, os:getenv()), + {ok, PWD} = file:get_cwd(), + (4 % buffsz + + 4 % flags + + 5 + length(Cmd) + 1 % "exec $Cmd" + + length(PWD) + 1 % $PWD + + 1 % nullbuff + + 4 % env_len + + EnvSize). %% Test bad 'args' options. bad_args(Config) when is_list(Config) -> -- cgit v1.2.3 From b63047af07a983ff7ff17d33736c505f866b88a5 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Fri, 17 Jun 2016 15:20:58 +0200 Subject: Increase time margin in timer_bif_SUITE:start_timer_1 test --- erts/emulator/test/timer_bif_SUITE.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/timer_bif_SUITE.erl b/erts/emulator/test/timer_bif_SUITE.erl index a5f11bd959..44f276f232 100644 --- a/erts/emulator/test/timer_bif_SUITE.erl +++ b/erts/emulator/test/timer_bif_SUITE.erl @@ -74,7 +74,7 @@ all() -> %% Basic start_timer/3 functionality start_timer_1(Config) when is_list(Config) -> Ref1 = erlang:start_timer(1000, self(), plopp), - ok = get(1100, {timeout, Ref1, plopp}), + ok = get(1400, {timeout, Ref1, plopp}), false = erlang:read_timer(Ref1), false = erlang:cancel_timer(Ref1), @@ -83,12 +83,12 @@ start_timer_1(Config) when is_list(Config) -> Ref2 = erlang:start_timer(1000, self(), plapp), Left2 = erlang:cancel_timer(Ref2), UpperLimit = 1000, - true = (Left2 > 900) and (Left2 =< UpperLimit), + true = (Left2 > 600) and (Left2 =< UpperLimit), empty = get_msg(), false = erlang:cancel_timer(Ref2), Ref3 = erlang:start_timer(1000, self(), plopp), - no_message = get(900, {timeout, Ref3, plopp}), + no_message = get(600, {timeout, Ref3, plopp}), ok. %% Basic send_after/3 functionality -- cgit v1.2.3 From 9e48c3bd4417b33b907c2479bc4a1e8cd79a34b3 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Mon, 20 Jun 2016 11:20:50 +0200 Subject: Skip nif_SUITE:consume_timeslice test when debug compiled --- erts/emulator/test/nif_SUITE.erl | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index a0e9f1bad6..b8fa7184b6 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -1443,6 +1443,17 @@ otp_9828_loop(Bin, Val) -> consume_timeslice(Config) when is_list(Config) -> + case {erlang:system_info(debug_compiled), + erlang:system_info(lock_checking)} of + {false, false} -> + consume_timeslice_test(Config); + {false, true} -> + {skipped, "Lock checking enabled"}; + _ -> + {skipped, "Debug compiled"} + end. + +consume_timeslice_test(Config) when is_list(Config) -> CONTEXT_REDS = 2000, Me = self(), Go = make_ref(), -- cgit v1.2.3 From 377b2cd04ec0cc8793b516f930fe19be98e21a3d Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Wed, 22 Jun 2016 16:53:13 +0200 Subject: Fix scheduler_SUITE:update_cpu_info test --- erts/emulator/test/scheduler_SUITE.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl index f18d79d770..936c171214 100644 --- a/erts/emulator/test/scheduler_SUITE.erl +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -793,13 +793,13 @@ update_cpu_info(Config) when is_list(Config) -> io:format("START - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n", [OldAff, OldOnline, erlang:system_info(scheduler_bindings)]), case {erlang:system_info(logical_processors_available), OldAff} of - {Avail, _} when Avail == unknown; OldAff == unknown -> + {Avail, _} when Avail == unknown; OldAff == unknown; OldAff == 1 -> %% Nothing much to test; just a smoke test case erlang:system_info(update_cpu_info) of unchanged -> ok; changed -> ok end; - _ -> + {Avail, _} -> try adjust_schedulers_online(), case erlang:system_info(schedulers_online) of @@ -810,7 +810,7 @@ update_cpu_info(Config) when is_list(Config) -> %% unset least significant bit Aff = (OldAff band (OldAff - 1)), set_affinity_mask(Aff), - Onln1 = Onln0 - 1, + Onln1 = Avail - 1, case adjust_schedulers_online() of {Onln0, Onln1} -> Onln1 = erlang:system_info(schedulers_online), -- cgit v1.2.3 From e5a13ef9d2f0a95b3dffa6add628fa7ed8e0509d Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Wed, 22 Jun 2016 16:54:24 +0200 Subject: Fix scheduler_SUITE:scheduler_threads test --- erts/emulator/test/scheduler_SUITE.erl | 35 ++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl index 936c171214..7f239f73e7 100644 --- a/erts/emulator/test/scheduler_SUITE.erl +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -1072,20 +1072,27 @@ scheduler_threads(Config) when is_list(Config) -> {Sched, HalfSchedOnln, _} = get_sstate(Config, "+SP:50"), %% Configure 2x scheduler threads only {TwiceSched, SchedOnln, _} = get_sstate(Config, "+SP 200"), - %% Test resetting the scheduler counts - ResetCmd = "+S "++FourSched++":"++FourSchedOnln++" +S 0:0", - {Sched, SchedOnln, _} = get_sstate(Config, ResetCmd), - %% Test negative +S settings, but only for SMP-enabled emulators - case SmpSupport of - false -> ok; - true -> - SchedMinus1 = Sched-1, - SchedOnlnMinus1 = SchedOnln-1, - {SchedMinus1, SchedOnlnMinus1, _} = get_sstate(Config, "+S -1"), - {Sched, SchedOnlnMinus1, _} = get_sstate(Config, "+S :-1"), - {SchedMinus1, SchedOnlnMinus1, _} = get_sstate(Config, "+S -1:-1") - end, - ok. + case {erlang:system_info(logical_processors), + erlang:system_info(logical_processors_available)} of + {LProc, LProcAvail} when is_integer(LProc), is_integer(LProcAvail) -> + %% Test resetting the scheduler counts + ResetCmd = "+S "++FourSched++":"++FourSchedOnln++" +S 0:0", + {LProc, LProcAvail, _} = get_sstate(Config, ResetCmd), + %% Test negative +S settings, but only for SMP-enabled emulators + case {SmpSupport, LProc > 1, LProcAvail > 1} of + {true, true, true} -> + SchedMinus1 = LProc-1, + SchedOnlnMinus1 = LProcAvail-1, + {SchedMinus1, SchedOnlnMinus1, _} = get_sstate(Config, "+S -1"), + {LProc, SchedOnlnMinus1, _} = get_sstate(Config, "+S :-1"), + {SchedMinus1, SchedOnlnMinus1, _} = get_sstate(Config, "+S -1:-1"), + ok; + _ -> + {comment, "Skipped reduced amount of schedulers test due to too few logical processors"} + end; + _ -> %% Skipped when missing info about logical processors... + {comment, "Skipped reset amount of schedulers test, and reduced amount of schedulers test due to too unknown amount of logical processors"} + end. dirty_scheduler_threads(Config) when is_list(Config) -> SmpSupport = erlang:system_info(smp_support), -- cgit v1.2.3 From 7f951996600d1d09c8afa422beadf7bdde772471 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Wed, 22 Jun 2016 16:54:49 +0200 Subject: Fix scheduler_SUITE:scheduler_suspend test --- erts/emulator/test/scheduler_SUITE.erl | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl index 7f239f73e7..a95de609aa 100644 --- a/erts/emulator/test/scheduler_SUITE.erl +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -1319,11 +1319,33 @@ scheduler_suspend_test(Config, Schedulers) -> true -> ok end, - erlang:system_info(schedulers_state) + until(fun () -> + {_A, B, C} = erlang:system_info( + schedulers_state), + B == C + end, + erlang:monotonic_time() + + erlang:convert_time_unit(1, + seconds, + native)), + erlang:system_info(schedulers_state) end]), stop_node(Node), ok. - + +until(Pred, MaxTime) -> + case Pred() of + true -> + true; + false -> + case erlang:monotonic_time() > MaxTime of + true -> + false; + false -> + receive after 100 -> ok end, + until(Pred, MaxTime) + end + end. sst0_loop(0) -> ok; -- cgit v1.2.3 From 46b3f3d62b2c202ad08af87130eee1e16bc464af Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Wed, 22 Jun 2016 16:55:25 +0200 Subject: Fix statistics_SUITE:scheduler_wall_time test --- erts/emulator/test/statistics_SUITE.erl | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/statistics_SUITE.erl b/erts/emulator/test/statistics_SUITE.erl index 71ef003b25..4a07c6a10a 100644 --- a/erts/emulator/test/statistics_SUITE.erl +++ b/erts/emulator/test/statistics_SUITE.erl @@ -311,7 +311,15 @@ scheduler_wall_time(Config) when is_list(Config) -> true -> exit({fullload, FullLoad}) end, - [exit(Pid, kill) || Pid <- [P1|HalfHogs++LastHogs]], + KillHog = fun (HP) -> + HPM = erlang:monitor(process, HP), + exit(HP, kill), + receive + {'DOWN', HPM, process, HP, killed} -> + ok + end + end, + [KillHog(Pid) || Pid <- [P1|HalfHogs++LastHogs]], AfterLoad = get_load(), {false,_} = {lists:any(fun(Load) -> Load > 25 end, AfterLoad),AfterLoad}, true = erlang:system_flag(scheduler_wall_time, false) -- cgit v1.2.3 From 7da791e738fbde05bbd6b881c940e896a217ef91 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Wed, 22 Jun 2016 17:25:40 +0200 Subject: Improve timer tests in driver_SUITE --- erts/emulator/test/driver_SUITE.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl index f134a197aa..68e2e1696f 100644 --- a/erts/emulator/test/driver_SUITE.erl +++ b/erts/emulator/test/driver_SUITE.erl @@ -401,7 +401,7 @@ try_timeouts(Port, Timeout) -> true -> try_timeouts(Port, Timeout div 2) end - after Timeout + ?delay -> + after Timeout + 100*?delay -> ct:fail("driver failed to timeout") end. @@ -437,7 +437,7 @@ try_cancel(Port, Timeout) -> Timeout == 0 -> ok; true -> try_cancel(Port, Timeout div 2) end - after ?delay -> + after 100*?delay -> ct:fail("No message from driver") end end. @@ -505,7 +505,7 @@ try_change_timer(Port, Timeout) -> true -> try_timeouts(Port, Timeout div 2) end - after Timeout + ?delay -> + after Timeout + 100*?delay -> ct:fail("driver failed to timeout") end. -- cgit v1.2.3 From 832985da5c5ca3f7635d77aaa31904d79adeb37e Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Thu, 23 Jun 2016 13:31:37 +0200 Subject: Cleanup in statistics_SUITE:runtime_update test --- erts/emulator/test/statistics_SUITE.erl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/statistics_SUITE.erl b/erts/emulator/test/statistics_SUITE.erl index 4a07c6a10a..a1f12ba93c 100644 --- a/erts/emulator/test/statistics_SUITE.erl +++ b/erts/emulator/test/statistics_SUITE.erl @@ -129,11 +129,15 @@ do_runtime_update(0) -> {comment,"Never close enough"}; do_runtime_update(N) -> {T1,Diff0} = statistics(runtime), - spawn_link(fun cpu_heavy/0), + {CPUHog, CPUHogMon} = spawn_opt(fun cpu_heavy/0,[link,monitor]), receive after 1000 -> ok end, {T2,Diff} = statistics(runtime), + unlink(CPUHog), + exit(CPUHog, kill), + true = is_integer(T1+T2+Diff0+Diff), io:format("T1 = ~p, T2 = ~p, Diff = ~p, T2-T1 = ~p", [T1,T2,Diff,T2-T1]), + receive {'DOWN',CPUHogMon,process,CPUHog,_} -> ok end, if T2 - T1 =:= Diff, 900 =< Diff, Diff =< 1500 -> ok; true -> do_runtime_update(N-1) @@ -321,6 +325,7 @@ scheduler_wall_time(Config) when is_list(Config) -> end, [KillHog(Pid) || Pid <- [P1|HalfHogs++LastHogs]], AfterLoad = get_load(), + io:format("AfterLoad=~p~n", [AfterLoad]), {false,_} = {lists:any(fun(Load) -> Load > 25 end, AfterLoad),AfterLoad}, true = erlang:system_flag(scheduler_wall_time, false) after -- cgit v1.2.3 From 412d7dfcfb667bb2b329b8e35c929c2b5abcc2b1 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 27 Jun 2016 18:40:36 +0200 Subject: erts: Fix spawn driver with relative cd option --- erts/emulator/test/port_SUITE.erl | 50 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index ee07699884..6115071b79 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -83,6 +83,7 @@ bad_port_messages/1, basic_ping/1, cd/1, + cd_relative/1, close_deaf_port/1, count_fds/1, dying_port/1, @@ -137,7 +138,7 @@ win_massive_client/1 ]). --export([do_iter_max_ports/2]). +-export([do_iter_max_ports/2, relative_cd/0]). %% Internal exports. -export([tps/3]). @@ -158,7 +159,7 @@ all() -> {group, multiple_packets}, parallell, dying_port, port_program_with_path, open_input_file_port, open_output_file_port, name1, env, huge_env, bad_env, cd, - bad_args, + cd_relative, bad_args, exit_status, iter_max_ports, count_fds, t_exit, {group, tps}, line, stderr_to_stdout, otp_3906, otp_4389, win_massive, mix_up_ports, otp_5112, otp_5119, @@ -1065,6 +1066,51 @@ cd(Config) when is_list(Config) -> end, ok. +%% Test that an emulator that has set it's cwd to +%% something other then when it started, can use +%% relative {cd,"./"} to open port and that cd will +%% be relative the new cwd and not the original +cd_relative(Config) -> + + Program = atom_to_list(lib:progname()), + DataDir = proplists:get_value(data_dir, Config), + TestDir = filename:join(DataDir, "dir"), + + Cmd = Program ++ " -pz " ++ filename:dirname(code:where_is_file("port_SUITE.beam")) ++ + " -noshell -s port_SUITE relative_cd -s erlang halt", + + _ = open_port({spawn, Cmd}, [{line, 256}, {cd, TestDir}]), + + receive + {_, {data, {eol, String}}} -> + case filename_equal(String, TestDir) of + true -> + ok; + false -> + ct:fail({cd_relative, String}) + end; + Other -> + ct:fail(Other) + end. + +relative_cd() -> + + Program = atom_to_list(lib:progname()), + ok = file:set_cwd(".."), + {ok, Cwd} = file:get_cwd(), + + Cmd = Program ++ " -pz " ++ Cwd ++ + " -noshell -s port_test pwd -s erlang halt", + + _ = open_port({spawn, Cmd}, [{line, 256}, {cd, "./dir"}, exit_status]), + + receive + {_, {data, {eol, String}}} -> + io:format("~s~n",[String]); + Other -> + io:format("ERROR: ~p~n",[Other]) + end. + filename_equal(A, B) -> case os:type() of {win32, _} -> -- cgit v1.2.3 From a93036e0cd9c3620ece4bfcb56c6b0c44abf9a58 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 1 Jul 2016 11:16:42 +0200 Subject: erts: Add port_SUITE:cd invalid dir testcase --- erts/emulator/test/port_SUITE.erl | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index 6115071b79..a683307722 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -1037,8 +1037,7 @@ cd(Config) when is_list(Config) -> Cmd = Program ++ " -pz " ++ DataDir ++ " -noshell -s port_test pwd -s erlang halt", _ = open_port({spawn, Cmd}, - [{cd, TestDir}, - {line, 256}]), + [{cd, TestDir}, {line, 256}]), receive {_, {data, {eol, String}}} -> case filename_equal(String, TestDir) of @@ -1064,7 +1063,29 @@ cd(Config) when is_list(Config) -> Other3 -> ct:fail({env, Other3}) end, - ok. + + InvalidDir = filename:join(DataDir, "invaliddir"), + try open_port({spawn, Cmd}, + [{cd, InvalidDir}, exit_status, {line, 256}]) of + _ -> + receive + {_, {exit_status, _}} -> + ok; + Other4 -> + ct:fail({env, Other4}) + end + catch error:eacces -> + %% This happens on Windows + ok + end, + + %% Check that there are no lingering messages + receive + Other5 -> + ct:fail({env, Other5}) + after 10 -> + ok + end. %% Test that an emulator that has set it's cwd to %% something other then when it started, can use -- cgit v1.2.3 From f0131c58c42a286c8b3f611b47106393a37197b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Mon, 23 May 2016 15:41:31 +0200 Subject: check_process_code: Sweep HiPE stack for literals Because check_process_code neglected checking the HiPE stack for references to the literal area, such references would survive the purge and subsequent deletion of a module and its literal area. These dangling references would then cause incorrect behaviour or even hard crashes of the VM. By simply adding a scan of the HiPE stack to check_process_code and erts_garbage_collect_literals, this problem is fixed. In order to support full stack walks without deleting the graylimit trap, a new stack walking interface function, nstack_walk_init_sdesc_ignore_trap() was introduced. --- erts/emulator/test/Makefile | 1 + erts/emulator/test/hipe_SUITE.erl | 64 +++++++++++++++++++++++++ erts/emulator/test/hipe_SUITE_data/literals.erl | 26 ++++++++++ erts/emulator/test/hipe_SUITE_data/ref_cell.erl | 64 +++++++++++++++++++++++++ 4 files changed, 155 insertions(+) create mode 100644 erts/emulator/test/hipe_SUITE.erl create mode 100644 erts/emulator/test/hipe_SUITE_data/literals.erl create mode 100644 erts/emulator/test/hipe_SUITE_data/ref_cell.erl (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index b580211eff..2e48c475d5 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -70,6 +70,7 @@ MODULES= \ guard_SUITE \ hash_SUITE \ hibernate_SUITE \ + hipe_SUITE \ list_bif_SUITE \ lttng_SUITE \ map_SUITE \ diff --git a/erts/emulator/test/hipe_SUITE.erl b/erts/emulator/test/hipe_SUITE.erl new file mode 100644 index 0000000000..3e682b8d88 --- /dev/null +++ b/erts/emulator/test/hipe_SUITE.erl @@ -0,0 +1,64 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2016. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +-module(hipe_SUITE). +-export([all/0, t_copy_literals/1]). + +all() -> + case erlang:system_info(hipe_architecture) of + undefined -> {skip, "HiPE is disabled"}; + _ -> [t_copy_literals] + end. + +t_copy_literals(doc) -> + "Check that BEAM literals referenced from HiPE stack are copied by" + " check_process_code"; +t_copy_literals(Config) when is_list(Config) -> + %% Compile the the ref_cell and literals modules. + Data = proplists:get_value(data_dir, Config), + Priv = proplists:get_value(priv_dir, Config), + RefFile = filename:join(Data, "ref_cell"), + {ok,ref_cell} = c:c(RefFile, [{outdir,Priv},native]), + true = code:is_module_native(ref_cell), + LitFile = filename:join(Data, "literals"), + {ok,literals} = c:c(LitFile, [{outdir,Priv}]), + + %% store references to literals on HiPE stacks + PA = ref_cell:start_link(), + ref_cell:call(PA, {put_res_of, fun literals:a/0}), + PB = ref_cell:start_link_deep(), + ref_cell:call(PB, {put_res_of, fun literals:b/0}), + + %% purge the literals + _ = (catch erlang:purge_module(literals)), + true = erlang:delete_module(literals), + true = erlang:purge_module(literals), + + %% check that the ex-literals are ok + [a,b,c] = ref_cell:call(PA, get), + {a,b,c} = ref_cell:call(PB, get), + + %% cleanup + ref_cell:call(PA, done), + ref_cell:call(PB, done), + _ = (catch erlang:purge_module(ref_cell)), + true = erlang:delete_module(ref_cell), + true = erlang:purge_module(ref_cell), + ok. diff --git a/erts/emulator/test/hipe_SUITE_data/literals.erl b/erts/emulator/test/hipe_SUITE_data/literals.erl new file mode 100644 index 0000000000..31e443970f --- /dev/null +++ b/erts/emulator/test/hipe_SUITE_data/literals.erl @@ -0,0 +1,26 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2016. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +-module(literals). + +-export([a/0, b/0]). + +a() -> [a,b,c]. +b() -> {a,b,c}. diff --git a/erts/emulator/test/hipe_SUITE_data/ref_cell.erl b/erts/emulator/test/hipe_SUITE_data/ref_cell.erl new file mode 100644 index 0000000000..2654e4077b --- /dev/null +++ b/erts/emulator/test/hipe_SUITE_data/ref_cell.erl @@ -0,0 +1,64 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2016. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +-module(ref_cell). + +-export([start_link/0, start_link_deep/0, call/2]). + +-compile(native). + +-define(DEPTH, 100). +-define(ALLOCS, 500). + +start_link() -> + spawn_link(fun() -> loop(undefined) end). + +start_link_deep() -> + spawn_link(fun() -> go_deep(?DEPTH) end). + +%% Create a stack large enough to get a graylimit trap placed next time there's +%% a minor gc. +go_deep(0) -> + alloc_some(?ALLOCS), + loop(undefined), + 0; +go_deep(Depth) -> + go_deep(Depth-1)+1. + +%% Do some allocation to trigger a minor gc +alloc_some(Amount) -> + Check = (Amount * (Amount + 1)) div 2, + Check = lists:sum(lists:seq(1, Amount)). + +call(Pid, Call) -> + Pid ! {Call, self()}, + receive {Pid, Res} -> Res end. + +loop(Thing) -> + receive + {done, Pid} -> Pid ! {self(), done}; + {{put_res_of, Fun}, Pid} -> + NewThing = Fun(), + Pid ! {self(), put}, + loop(NewThing); + {get, Pid} -> + Pid ! {self(), Thing}, + loop(Thing) + end. -- cgit v1.2.3 From 53bf2a9593a2f34151016f7d84fad6d213d76ee9 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 7 Jul 2016 20:59:28 +0200 Subject: erts: Check if return_to trace is enabled for bif We have to do an extra check if the return_to trace is enabled here as it may have been cleared by the bif after the flags where created by the call_trace. --- erts/emulator/test/trace_local_SUITE.erl | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/trace_local_SUITE.erl b/erts/emulator/test/trace_local_SUITE.erl index 74c05f24e0..c297acd78b 100644 --- a/erts/emulator/test/trace_local_SUITE.erl +++ b/erts/emulator/test/trace_local_SUITE.erl @@ -439,6 +439,14 @@ return_test() -> ?RT(?MODULE,slave,2), shutdown(), ?NM, + + %% Test a regression where turning off return_to tracing + %% on yourself would cause a segfault. + Pid = setup([call,return_to]), + erlang:trace_pattern({'_','_','_'},[],[local]), + apply_slave(erlang,trace,[Pid, false, [all]]), + shutdown(), + ok. on_and_off_test() -> -- cgit v1.2.3 From da560498a422107d3ff0076a1255078e829e380d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 21 Jul 2016 16:23:38 +0200 Subject: erts: Update maps entropy tests --- erts/emulator/test/map_SUITE.erl | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/map_SUITE.erl b/erts/emulator/test/map_SUITE.erl index b3870f0313..5af676c409 100644 --- a/erts/emulator/test/map_SUITE.erl +++ b/erts/emulator/test/map_SUITE.erl @@ -77,6 +77,7 @@ t_ets/1, t_dets/1, t_tracing/1, + t_hash_entropy/1, %% instruction-level tests t_has_map_fields/1, @@ -140,6 +141,7 @@ all() -> [t_build_and_match_literals, t_build_and_match_literals_large, t_pdict, t_ets, t_tracing, + t_hash_entropy, %% instruction-level tests t_has_map_fields, @@ -3020,6 +3022,39 @@ do_badmap_17(Config) -> id(I) -> I. +%% OTP-13763 +t_hash_entropy(Config) when is_list(Config) -> + %% entropy bug in 18.3, 19.0 + M1 = maps:from_list([{#{"id" => I}, ok}||I <- lists:seq(1,50000)]), + + #{ #{"id" => 100} := ok, + #{"id" => 200} := ok, + #{"id" => 300} := ok, + #{"id" => 400} := ok, + #{"id" => 500} := ok, + #{"id" => 600} := ok, + #{"id" => 700} := ok, + #{"id" => 800} := ok, + #{"id" => 900} := ok, + #{"id" => 25061} := ok, + #{"id" => 39766} := ok } = M1, + + M0 = maps:from_list([{I,ok}||I <- lists:seq(1,33)]), + M2 = maps:from_list([{M0#{"id" => I}, ok}||I <- lists:seq(1,50000)]), + + ok = maps:get(M0#{"id" => 100}, M2), + ok = maps:get(M0#{"id" => 200}, M2), + ok = maps:get(M0#{"id" => 300}, M2), + ok = maps:get(M0#{"id" => 400}, M2), + ok = maps:get(M0#{"id" => 500}, M2), + ok = maps:get(M0#{"id" => 600}, M2), + ok = maps:get(M0#{"id" => 700}, M2), + ok = maps:get(M0#{"id" => 800}, M2), + ok = maps:get(M0#{"id" => 900}, M2), + ok = maps:get(M0#{"id" => 25061}, M2), + ok = maps:get(M0#{"id" => 39766}, M2), + ok. + %% OTP-13146 %% Provoke major GC with a lot of "fat" maps on external format in msg queue %% causing heap fragments to be allocated. -- cgit v1.2.3 From f8dc8bc39cfbd66c4187fc7da0071705e20cde4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 26 Jul 2016 14:43:59 +0200 Subject: erts: Fix whitespaces in distribution_SUITE --- erts/emulator/test/distribution_SUITE.erl | 95 ++++++++++++++----------------- 1 file changed, 42 insertions(+), 53 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl index c6939a695d..6895b08d2e 100644 --- a/erts/emulator/test/distribution_SUITE.erl +++ b/erts/emulator/test/distribution_SUITE.erl @@ -43,7 +43,7 @@ lost_exit/1, link_to_dead/1, link_to_dead_new_node/1, applied_monitor_node/1, ref_port_roundtrip/1, nil_roundtrip/1, trap_bif_1/1, trap_bif_2/1, trap_bif_3/1, - stop_dist/1, + stop_dist/1, dist_auto_connect_never/1, dist_auto_connect_once/1, dist_parallel_send/1, atom_roundtrip/1, @@ -72,7 +72,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap, {minutes, 4}}]. -all() -> +all() -> [ping, {group, bulk_send}, {group, local_send}, link_to_busy, exit_to_busy, lost_exit, link_to_dead, link_to_dead_new_node, applied_monitor_node, @@ -83,7 +83,7 @@ all() -> bad_dist_structure, {group, bad_dist_ext}, start_epmd_false, epmd_module]. -groups() -> +groups() -> [{bulk_send, [], [bulk_send_small, bulk_send_big, bulk_send_bigbig]}, {local_send, [], [local_send_small, local_send_big, local_send_legal]}, @@ -844,59 +844,50 @@ dist_auto_connect_once(Config) when is_list(Config) -> %% Result is sent here through relay node. dist_auto_connect_never(Config) when is_list(Config) -> Self = self(), - {ok, RelayNode} = - start_node(dist_auto_connect_relay), - spawn(RelayNode, + {ok, RelayNode} = start_node(dist_auto_connect_relay), + spawn(RelayNode, fun() -> register(dist_auto_connect_relay, self()), - dist_auto_connect_relay(Self) + dist_auto_connect_relay(Self) end), {ok, Handle} = dist_auto_connect_start(dist_auto_connect, never), - Result = - receive - {do_dist_auto_connect, ok} -> - ok; - {do_dist_auto_connect, Error} -> - {error, Error}; - Other -> - {error, Other} - after 32000 -> - timeout - end, + Result = receive + {do_dist_auto_connect, ok} -> + ok; + {do_dist_auto_connect, Error} -> + {error, Error}; + Other -> + {error, Other} + after 32000 -> + timeout + end, stop_node(RelayNode), - Stopped = dist_auto_connect_stop(Handle), - Junk = - receive - {do_dist_auto_connect, _} = J -> - J - after 0 -> - ok - end, + Stopped = dist_auto_connect_stop(Handle), + Junk = receive + {do_dist_auto_connect, _} = J -> J + after 0 -> ok + end, {ok, ok, ok} = {Result, Stopped, Junk}, ok. do_dist_auto_connect([never]) -> Node = list_to_atom("dist_auto_connect_relay@" ++ hostname()), - io:format("~p:do_dist_auto_connect([false]) Node=~p~n", - [?MODULE, Node]), + io:format("~p:do_dist_auto_connect([false]) Node=~p~n", [?MODULE, Node]), Ping = net_adm:ping(Node), - io:format("~p:do_dist_auto_connect([false]) Ping=~p~n", - [?MODULE, Ping]), + io:format("~p:do_dist_auto_connect([false]) Ping=~p~n", [?MODULE, Ping]), Result = case Ping of pang -> ok; _ -> {error, Ping} end, - io:format("~p:do_dist_auto_connect([false]) Result=~p~n", - [?MODULE, Result]), + io:format("~p:do_dist_auto_connect([false]) Result=~p~n", [?MODULE, Result]), net_kernel:connect_node(Node), catch {dist_auto_connect_relay, Node} ! {do_dist_auto_connect, Result}; % receive after 1000 -> ok end, % halt(); do_dist_auto_connect(Arg) -> - io:format("~p:do_dist_auto_connect(~p)~n", - [?MODULE, Arg]), + io:format("~p:do_dist_auto_connect(~p)~n", [?MODULE, Arg]), receive after 10000 -> ok end, halt(). @@ -912,11 +903,11 @@ dist_auto_connect_start(Name, Value) when is_list(Name), is_atom(Value) -> [%"xterm -e ", atom_to_list(lib:progname()), % " -noinput ", - " -detached ", + " -detached ", long_or_short(), " ", Name, " -setcookie ", Cookie, " -pa ", ModuleDir, - " -s ", atom_to_list(?MODULE), + " -s ", atom_to_list(?MODULE), " do_dist_auto_connect ", ValueStr, " -kernel dist_auto_connect ", ValueStr]), io:format("~p:dist_auto_connect_start() cmd: ~p~n", [?MODULE, Cmd]), @@ -947,7 +938,7 @@ dist_auto_connect_stop(Port, Node, Pid, N) when is_integer(N) -> end. -dist_auto_connect_relay(Parent) -> +dist_auto_connect_relay(Parent) -> receive X -> catch Parent ! X end, @@ -1321,7 +1312,7 @@ get_conflicting_unicode_atoms(CIX, N) -> start_monitor(Offender,P) -> Parent = self(), Q = spawn(Offender, - fun () -> + fun () -> Ref = erlang:monitor(process,P), Parent ! {self(),ref,Ref}, receive @@ -1458,8 +1449,8 @@ bad_dist_structure(Config) when is_list(Config) -> pong = rpc:call(Victim, net_adm, ping, [Offender]), P ! two, P ! check_msgs, - receive - {P, messages_checked} -> ok + receive + {P, messages_checked} -> ok after 5000 -> exit(victim_is_dead) end, @@ -1765,7 +1756,7 @@ send_bad_structure(Offender,Victim,Bad,WhereToPutSelf,PayLoad) -> pong = net_adm:ping(Node), DPrt = dport(Node), Bad1 = case WhereToPutSelf of - 0 -> + 0 -> Bad; N when N > 0 -> setelement(N,Bad,self()) @@ -1779,8 +1770,8 @@ send_bad_structure(Offender,Victim,Bad,WhereToPutSelf,PayLoad) -> port_command(DPrt, DData), Parent ! {DData,Done} end), - receive - {WhatSent,Done} -> + receive + {WhatSent,Done} -> io:format("Offender sent ~p~n",[WhatSent]), ok after 5000 -> @@ -1887,7 +1878,7 @@ dmsg_fake_hdr2() -> 1, size(A2), A2, 2, size(A3), A3]. -dmsg_ext(Term) -> +dmsg_ext(Term) -> <<131, Res/binary>> = term_to_binary(Term), Res. @@ -1972,7 +1963,7 @@ start_node(Name, Args, Rel) when is_atom(Name), is_list(Rel) -> [] -> []; _ -> [{erl,[{release,Rel}]}] end, - test_server:start_node(Name, slave, + test_server:start_node(Name, slave, [{args, Args++" -setcookie "++Cookie++" -pa \""++Pa++"\""} | RelArg]); @@ -2040,17 +2031,15 @@ inet_rpc_server_loop(Sock) -> start_relay_node(Node, Args) -> Pa = filename:dirname(code:which(?MODULE)), Cookie = "NOT"++atom_to_list(erlang:get_cookie()), - {ok, LSock} = gen_tcp:listen(0, [binary, {packet, 4}, - {active, false}]), + {ok, LSock} = gen_tcp:listen(0, [binary, {packet, 4}, {active, false}]), {ok, Port} = inet:port(LSock), {ok, Host} = inet:gethostname(), RunArg = "-run " ++ atom_to_list(?MODULE) ++ " inet_rpc_server " ++ Host ++ " " ++ integer_to_list(Port), - {ok, NN} = - test_server:start_node(Node, peer, - [{args, Args ++ - " -setcookie "++Cookie++" -pa "++Pa++" "++ - RunArg}]), + {ok, NN} = test_server:start_node(Node, peer, + [{args, Args ++ + " -setcookie "++Cookie++" -pa "++Pa++" "++ + RunArg}]), [N,H] = string:tokens(atom_to_list(NN),"@"), {ok, Sock} = gen_tcp:accept(LSock), pang = net_adm:ping(NN), @@ -2066,7 +2055,7 @@ wait_dead(N,H,0) -> wait_dead(N,H,X) -> case erl_epmd:port_please(N,H) of {port,_,_} -> - receive + receive after 1000 -> ok end, -- cgit v1.2.3 From 45fba6d24258f079859bd28f6deafbbba6b7c152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 26 Jul 2016 15:55:56 +0200 Subject: erts: Fix epmd_module testcase Regression from OTP-13770 (84549af1c996657aedee1263afec28b21bfa42a4) --- erts/emulator/test/distribution_SUITE.erl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl index 6895b08d2e..159fbc806b 100644 --- a/erts/emulator/test/distribution_SUITE.erl +++ b/erts/emulator/test/distribution_SUITE.erl @@ -66,7 +66,7 @@ sendersender/4, sendersender2/4]). %% epmd_module exports --export([start_link/0, register_node/2, port_please/2]). +-export([start_link/0, register_node/2, register_node/3, port_please/2]). suite() -> [{ct_hooks,[ts_install_cth]}, @@ -1925,7 +1925,9 @@ epmd_module(Config) when is_list(Config) -> start_link() -> ignore. -register_node(_Name, Port) -> +register_node(Name, Port) -> + register_node(Name, Port, inet_tcp). +register_node(_Name, Port, _Driver) -> %% Save the port number we're listening on. application:set_env(kernel, dist_listen_port, Port), Creation = rand:uniform(3), -- cgit v1.2.3 From 99a29386cb1a62bc7e9c205d897cd20017c598b4 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Thu, 21 Jul 2016 19:07:16 +0200 Subject: Ignore long time failures during high CPU utilization --- erts/emulator/test/long_timers_test.erl | 188 ++++++++++++++++++++++++++------ erts/emulator/test/z_SUITE.erl | 8 +- 2 files changed, 162 insertions(+), 34 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/long_timers_test.erl b/erts/emulator/test/long_timers_test.erl index 7c055a31f9..90efe1292c 100644 --- a/erts/emulator/test/long_timers_test.erl +++ b/erts/emulator/test/long_timers_test.erl @@ -27,11 +27,16 @@ %%% Created : 21 Aug 2006 by Rickard Green %%%------------------------------------------------------------------- +-define(HIGH_CPU_INFO, "Ignored due to high CPU utilization."). +-define(MISSING_CPU_INFO, "Ignored due to missing CPU utilization information."). -define(MAX_TIMEOUT, 60). % Minutes --define(MAX_LATE_MS, 15*1000). % Milliseconds +-define(MAX_LATE_MS, 1000). % Milliseconds -define(REG_NAME, '___LONG___TIMERS___TEST___SERVER___'). +-define(HIGH_UTIL, 96.0). +-define(UTIL_INTERVAL, 10000). + -define(DRV_NAME, timer_driver). % First byte in communication with the timer driver @@ -72,52 +77,149 @@ check_result() -> receive {'DOWN', Mon, process, _, Reason} -> {?REG_NAME, 'DOWN', Reason}; - {result, ?REG_NAME, TORs, Start, End} -> + {result, ?REG_NAME, TORs, Start, End, UtilData} -> erlang:demonitor(Mon), receive {'DOWN', Mon, _, _, _} -> ok after 0 -> ok end, stop_node(Node), - check(TORs, ms((End - Start) - max_late()), ok) + Res = check(TORs, Start, End, UtilData, ms((End - Start) - max_late()), ok), + io:format("Start = ~p~n End = ~p~n UtilData = ~p~n", [Start, End, UtilData]), + Res end. +res(New, Old) when New == failed; Old == failed -> + failed; +res(New, Old) when New == missing_cpu_info; Old == missing_cpu_info -> + missing_cpu_info; +res(New, Old) when New == high_cpu; Old == high_cpu -> + high_cpu; +res(New, _Old) -> + New. + check([#timeout_rec{timeout = Timeout, type = Type, timeout_diff = undefined} | TORs], + Start, + End, + UtilData, NeedRes, - _Ok) when Timeout < NeedRes -> - io:format("~p timeout = ~p ms failed! No timeout.~n", - [Type, Timeout]), - check(TORs, NeedRes, failed); + Ok) when Timeout < NeedRes -> + {NewOk, HCPU} = case had_high_cpu_util(Start, + Timeout, + End - Timeout*1000, + UtilData) of + yes -> {res(high_cpu, Ok), ?HIGH_CPU_INFO}; + no -> {res(failed, Ok), ""}; + missing -> {res(missing_cpu_info, Ok), "FAILED", ?MISSING_CPU_INFO} + end, + io:format("~p timeout = ~p ms FAILED! No timeout. ~s~n", + [Type, Timeout, HCPU]), + check(TORs, Start, End, UtilData, NeedRes, NewOk); check([#timeout_rec{timeout_diff = undefined} | TORs], + Start, + End, + UtilData, NeedRes, Ok) -> - check(TORs, NeedRes, Ok); + check(TORs, Start, End, UtilData, NeedRes, Ok); check([#timeout_rec{timeout = Timeout, type = Type, timeout_diff = {error, Reason}} | TORs], + Start, + End, + UtilData, NeedRes, _Ok) -> - io:format("~p timeout = ~p ms failed! exit reason ~p~n", + io:format("~p timeout = ~p ms FAILED! exit reason ~p~n", [Type, Timeout, Reason]), - check(TORs, NeedRes, failed); + check(TORs, Start, End, UtilData, NeedRes, failed); check([#timeout_rec{timeout = Timeout, type = Type, timeout_diff = TimeoutDiff} | TORs], + Start, + End, + UtilData, NeedRes, Ok) -> - {NewOk, SuccessStr} = case ((0 =< TimeoutDiff) - andalso (TimeoutDiff =< max_late())) of - true -> {Ok, "succeeded"}; - false -> {failed, "FAILED"} + {NewOk, SuccessStr, HCPU} = case {(0 =< TimeoutDiff), + (TimeoutDiff =< max_late())} of + {true, true} -> + {res(ok, Ok), "succeeded", ""}; + {false, _} -> + {res(failed, Ok), "FAILED", ""}; + _ -> + case had_high_cpu_util(Start, + Timeout, + TimeoutDiff, + UtilData) of + yes -> {res(high_cpu, Ok), "FAILED", ?HIGH_CPU_INFO}; + no -> {res(failed, Ok), "FAILED", ""}; + missing -> {res(missing_cpu_info, Ok), "FAILED", ?MISSING_CPU_INFO} + end end, - io:format("~s timeout = ~s ms ~s! timeout diff = ~s.~n", + io:format("~s timeout = ~s ms ~s! timeout diff = ~s. ~s~n", [type_str(Type), time_str(Timeout), SuccessStr, - time_str(TimeoutDiff, erlang:convert_time_unit(1, seconds, native))]), - check(TORs, NeedRes, NewOk); -check([], _NeedRes, Ok) -> + time_str(TimeoutDiff, 1000000), + HCPU]), + check(TORs, Start, End, UtilData, NeedRes, NewOk); +check([],_Start,_End,_UtilData,_NeedRes, Ok) -> Ok. +% TargetTimeout in ms, other in us. +had_high_cpu_util(StartTime, + TargetTimeout, + TimeoutDiff, + UtilData) -> + TargetTo = StartTime + TargetTimeout*1000, + ActTo = TargetTo + TimeoutDiff, + hcpu(ActTo, TargetTo, UtilData). + +hcpu(_ActTo, _TargetTo, [{UT, 0} | _] = UD) -> + missing; %% Util is the integer zero when not supported... +%% UT2 =:= UT1 +hcpu(ActTo, TargetTo, [{UT, _}, {UT, _} | _] = UD) -> + hcpu(ActTo, TargetTo, tl(UD)); +%% UT2 > UT1 > ActTo > TargetTo +hcpu(ActTo, TargetTo, [{_UT2, _}, {UT1, _} | _] = UD) when UT1 > ActTo -> + hcpu(ActTo, TargetTo, tl(UD)); +%% UT2 >= ActTo > TargetTo >= UT1 +hcpu(ActTo, TargetTo, + [{UT2, U}, {UT1, _} | _]) when UT2 >= ActTo, + TargetTo >= UT1 -> + case U >= (((ActTo - TargetTo) / (UT2 - UT1)) + * (?HIGH_UTIL/100.0)) of + true -> yes; + false -> no + end; +%% UT2 >= ActTo >= UT1 > TargetTo +hcpu(ActTo, TargetTo, + [{UT2, U}, {UT1, _} | _] = UD) when UT2 >= ActTo, + ActTo >= UT1, + UT1 > TargetTo -> + case U >= (((ActTo - UT1) / (UT2 - UT1)) + * (?HIGH_UTIL/100.0)) of + true -> hcpu(ActTo, TargetTo, tl(UD)); + false -> no + end; +%% ActTo > UT2 >= TargetTo >= UT1 +hcpu(ActTo, TargetTo, + [{UT2, U}, {UT1, _} | _]) when ActTo > UT2, + TargetTo >= UT1 -> + case U >= (((UT2 - TargetTo) / (UT2 - UT1)) + * (?HIGH_UTIL/100.0)) of + true -> yes; + false -> no + end; +%% ActTo > UT2 > UT1 > TargetTo +hcpu(ActTo, TargetTo, + [{UT2, U}, {UT1, _} | _] = UD) when ActTo > UT2, + UT1 > TargetTo -> + case U >= ?HIGH_UTIL of + true -> hcpu(ActTo, TargetTo, tl(UD)); + false -> no + end. + type_str(receive_after) -> "receive ... after"; type_str(bif_timer) -> "BIF timer"; type_str(driver) -> "driver". @@ -142,24 +244,24 @@ unit_str(Res) -> Res. to_diff(Timeout, Start, Stop) -> %% 'Timeout' in milli seconds - %% 'Start', 'Stop', and result in native unit - (Stop - Start) - erlang:convert_time_unit(Timeout, milli_seconds, native). + %% 'Start', 'Stop', and result in micro seconds + (Stop - Start) - Timeout*1000. ms(Time) -> - erlang:convert_time_unit(Time, native, milli_seconds). + erlang:convert_time_unit(Time, micro_seconds, milli_seconds). max_late() -> - erlang:convert_time_unit(?MAX_LATE_MS, milli_seconds, native). + erlang:convert_time_unit(?MAX_LATE_MS, milli_seconds, micro_seconds). receive_after(Timeout) -> - Start = erlang:monotonic_time(), + Start = erlang:monotonic_time(micro_seconds), receive {get_result, ?REG_NAME} -> ?REG_NAME ! #timeout_rec{pid = self(), type = receive_after, timeout = Timeout} after Timeout -> - Stop = erlang:monotonic_time(), + Stop = erlang:monotonic_time(micro_seconds), receive {get_result, ?REG_NAME} -> ?REG_NAME ! #timeout_rec{pid = self(), @@ -174,7 +276,7 @@ receive_after(Timeout) -> driver(Timeout) -> Port = open_port({spawn, ?DRV_NAME},[]), link(Port), - Start = erlang:monotonic_time(), + Start = erlang:monotonic_time(micro_seconds), erlang:port_command(Port, <>), receive {get_result, ?REG_NAME} -> @@ -182,7 +284,7 @@ driver(Timeout) -> type = driver, timeout = Timeout}; {Port,{data,[?TIMER]}} -> - Stop = erlang:monotonic_time(), + Stop = erlang:monotonic_time(micro_seconds), unlink(Port), true = erlang:port_close(Port), receive @@ -197,7 +299,7 @@ driver(Timeout) -> end. bif_timer(Timeout) -> - Start = erlang:monotonic_time(), + Start = erlang:monotonic_time(micro_seconds), Tmr = erlang:start_timer(Timeout, self(), ok), receive {get_result, ?REG_NAME} -> @@ -205,7 +307,7 @@ bif_timer(Timeout) -> type = bif_timer, timeout = Timeout}; {timeout, Tmr, ok} -> - Stop = erlang:monotonic_time(), + Stop = erlang:monotonic_time(micro_seconds), receive {get_result, ?REG_NAME} -> ?REG_NAME ! #timeout_rec{pid = self(), @@ -218,13 +320,22 @@ bif_timer(Timeout) -> end. test(Starter, DrvDir, StartDone) -> + process_flag(priority, high), erl_ddll:start(), ok = load_driver(DrvDir, ?DRV_NAME), process_flag(trap_exit, true), register(?REG_NAME, self()), {group_leader, GL} = process_info(whereis(net_kernel),group_leader), group_leader(GL, self()), - Start = erlang:monotonic_time(), + try + application:start(sasl), + application:start(os_mon) + catch + _ : _ -> + ok + end, + UtilData = new_util(), + Start = erlang:monotonic_time(micro_seconds), TORs = lists:map(fun (Min) -> TO = Min*60*1000, [#timeout_rec{pid = spawn_opt( @@ -252,16 +363,27 @@ test(Starter, DrvDir, StartDone) -> lists:seq(1, ?MAX_TIMEOUT)), FlatTORs = lists:flatten(TORs), Starter ! StartDone, - test_loop(FlatTORs, Start). + test_loop(FlatTORs, Start, UtilData). + +new_util() -> + new_util([]). + +new_util(UtilData) -> + Util = cpu_sup:util(), + Time = erlang:monotonic_time(micro_seconds), + [{Time, Util} | UtilData]. -test_loop(TORs, Start) -> +test_loop(TORs, Start, UtilData) -> receive {get_result, ?REG_NAME, Pid} -> - End = erlang:monotonic_time(), - Pid ! {result, ?REG_NAME, get_test_results(TORs), Start, End}, + End = erlang:monotonic_time(micro_seconds), + EndUtilData = new_util(UtilData), + Pid ! {result, ?REG_NAME, get_test_results(TORs), Start, End, EndUtilData}, erl_ddll:unload_driver(?DRV_NAME), erl_ddll:stop(), exit(bye) + after ?UTIL_INTERVAL -> + test_loop(TORs, Start, new_util(UtilData)) end. get_test_results(TORs) -> diff --git a/erts/emulator/test/z_SUITE.erl b/erts/emulator/test/z_SUITE.erl index d1085c1958..ab56018373 100644 --- a/erts/emulator/test/z_SUITE.erl +++ b/erts/emulator/test/z_SUITE.erl @@ -191,7 +191,13 @@ node_container_refc_check(Config) when is_list(Config) -> ok. long_timers(Config) when is_list(Config) -> - ok = long_timers_test:check_result(). + case long_timers_test:check_result() of + ok -> ok; + high_cpu -> {comment, "Ignored failures due to high CPU utilization"}; + missing_cpu_info -> {comment, "Ignored failures due to missing CPU utilization information"}; + Fail -> ct:fail(Fail) + end. + pollset_size(Config) when is_list(Config) -> Name = pollset_size_testcase_initial_state_holder, -- cgit v1.2.3 From 799185848f6557754031269b1232d52420f3bda5 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Thu, 21 Jul 2016 19:09:23 +0200 Subject: Allow larger timeout delay in driver_SUITE --- erts/emulator/test/driver_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl index 68e2e1696f..a3df0bb2db 100644 --- a/erts/emulator/test/driver_SUITE.erl +++ b/erts/emulator/test/driver_SUITE.erl @@ -114,7 +114,7 @@ -define(MAX_DATA_SIZE, 16384). % This is the allowed delay when testing the driver timer functionality --define(delay, 100). +-define(delay, 400). -define(heap_binary_size, 64). -- cgit v1.2.3 From 58d8a3ac4d491c8cd962ac0839a56cd1a0e339f9 Mon Sep 17 00:00:00 2001 From: Dmytro Lytovchenko Date: Mon, 13 Jun 2016 12:05:55 +0200 Subject: Option to erlang:garbage_collect to request minor (generational) GC Note: Minor GC option is a hint, and GC may still decide to run fullsweep. Test case for major and minor gc on self Test case for major and minor gs on some other process + async gc test check docs fix --- erts/emulator/test/gc_SUITE.erl | 103 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/gc_SUITE.erl b/erts/emulator/test/gc_SUITE.erl index 8a600b7d9f..35dd147550 100644 --- a/erts/emulator/test/gc_SUITE.erl +++ b/erts/emulator/test/gc_SUITE.erl @@ -23,15 +23,26 @@ -module(gc_SUITE). -include_lib("common_test/include/ct.hrl"). +-include_lib("eunit/include/eunit.hrl"). + -export([all/0, suite/0]). --export([grow_heap/1, grow_stack/1, grow_stack_heap/1, max_heap_size/1]). +-export([ + grow_heap/1, + grow_stack/1, + grow_stack_heap/1, + max_heap_size/1, + minor_major_gc_option_async/1, + minor_major_gc_option_self/1 +]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [grow_heap, grow_stack, grow_stack_heap, max_heap_size]. + [grow_heap, grow_stack, grow_stack_heap, max_heap_size, + minor_major_gc_option_self, + minor_major_gc_option_async]. %% Produce a growing list of elements, @@ -190,3 +201,91 @@ long_receive() -> after 10000 -> ok end. + +minor_major_gc_option_self(_Config) -> + Endless = fun Endless() -> + receive + {gc, Type} -> erlang:garbage_collect(self(), [{type, Type}]) + after 100 -> ok end, + Endless() + end, + + %% Try as major, a test process will self-trigger GC + P1 = spawn(Endless), + erlang:garbage_collect(P1, []), + erlang:trace(P1, true, [garbage_collection]), + P1 ! {gc, major}, + expect_trace_messages(P1, [gc_major_start, gc_major_end]), + erlang:trace(P1, false, [garbage_collection]), + erlang:exit(P1, kill), + + %% Try as minor, a test process will self-trigger GC + P2 = spawn(Endless), + erlang:garbage_collect(P2, []), + erlang:trace(P2, true, [garbage_collection]), + P2 ! {gc, minor}, + expect_trace_messages(P2, [gc_minor_start, gc_minor_end]), + erlang:trace(P2, false, [garbage_collection]), + erlang:exit(P2, kill). + +minor_major_gc_option_async(_Config) -> + Endless = fun Endless() -> + receive after 100 -> ok end, + Endless() + end, + + %% Try with default option, must be major gc + P1 = spawn(Endless), + erlang:garbage_collect(P1, []), + erlang:trace(P1, true, [garbage_collection]), + erlang:garbage_collect(P1, []), + expect_trace_messages(P1, [gc_major_start, gc_major_end]), + erlang:trace(P1, false, [garbage_collection]), + erlang:exit(P1, kill), + + %% Try with the 'major' type + P2 = spawn(Endless), + erlang:garbage_collect(P2, []), + erlang:trace(P2, true, [garbage_collection]), + erlang:garbage_collect(P2, [{type, major}]), + expect_trace_messages(P2, [gc_major_start, gc_major_end]), + erlang:trace(P2, false, [garbage_collection]), + erlang:exit(P2, kill), + + %% Try with 'minor' option, once + P3 = spawn(Endless), + erlang:garbage_collect(P3, []), + erlang:trace(P3, true, [garbage_collection]), + erlang:garbage_collect(P3, [{type, minor}]), + expect_trace_messages(P3, [gc_minor_start, gc_minor_end]), + erlang:trace(P3, false, [garbage_collection]), + erlang:exit(P3, kill), + + %% Try with 'minor' option, once, async + P4 = spawn(Endless), + Ref = erlang:make_ref(), + erlang:garbage_collect(P4, []), + erlang:trace(P4, true, [garbage_collection]), + ?assertEqual(async, + erlang:garbage_collect(P4, [{type, minor}, {async, Ref}])), + expect_trace_messages(P4, [gc_minor_start, gc_minor_end]), + erlang:trace(P4, false, [garbage_collection]), + receive {garbage_collect, Ref, true} -> ok; + Other4 -> ct:pal("Unexpected message: ~p~n" + ++ "while waiting for async gc result", [Other4]) + after 2000 -> ?assert(false) + end, + erlang:exit(P4, kill). + +%% Given a list of atoms, trace tags - receives messages and checks if they are +%% trace events, and if the tag matches. Else will crash failing the test. +expect_trace_messages(_Pid, []) -> ok; +expect_trace_messages(Pid, [Tag | TraceTags]) -> + receive + {trace, Pid, Tag, _Data} -> ok; + AnythingElse -> + ct:pal("Unexpected message: ~p~nWhile expected {trace, _, ~p, _}", + [AnythingElse, Tag]), + ?assert(false) + end, + expect_trace_messages(Pid, TraceTags). -- cgit v1.2.3 From f5a1c56f0ab2a276b5c2add54b8b0d6d276e1361 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 12 Aug 2016 16:18:25 +0200 Subject: erts: Fix port monitor memory leak --- erts/emulator/test/port_SUITE.erl | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index 5c0bfdffd4..a9814d7df9 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -104,6 +104,7 @@ mon_port_name_demonitor/1, mon_port_named/1, mon_port_origin_dies/1, + mon_port_owner_dies/1, mon_port_pid_demonitor/1, mon_port_remote_on_remote/1, mon_port_driver_die/1, @@ -173,6 +174,7 @@ all() -> mon_port_remote_on_remote, mon_port_bad_remote_on_local, mon_port_origin_dies, + mon_port_owner_dies, mon_port_named, mon_port_bad_named, mon_port_pid_demonitor, @@ -2637,6 +2639,29 @@ mon_port_origin_dies(Config) -> Port5 ! {self(), {command, <<"1">>}}, % make port quit ok. +%% Port and Monitor owner dies before port is closed +%% This testcase checks for a regression memory leak in erts +%% when the controlling and monitoring process is the same process +%% and the process dies +mon_port_owner_dies(Config) -> + Self = self(), + Proc = spawn(fun() -> + Port = create_port(Config, ["-h1", "-q"]), + Self ! {test_started, Port}, + erlang:monitor(port, Port), + receive stop -> ok end + end), + erlang:monitor(process, Proc), % we want to sync with its death + Port = receive {test_started,P} -> P + after 1000 -> ?assert(false) end, + ?assertMatch({proc_monitors, true, port_monitored_by, true}, + port_is_monitored(Proc, Port)), + Proc ! stop, + %% receive from monitor + receive ExitP5 -> ?assertMatch({'DOWN', _, process, Proc, _}, ExitP5) + after 1000 -> ?assert(false) end, + ok. + %% Monitor a named port mon_port_named(Config) -> Name6 = test_port6, -- cgit v1.2.3 From fc85e401ee279cc3b69635a71ffa93544ce5b99d Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Wed, 24 Aug 2016 14:24:34 +0200 Subject: Update test-cases to use new symbolic time units --- erts/emulator/test/after_SUITE.erl | 4 +-- erts/emulator/test/alloc_SUITE.erl | 2 +- erts/emulator/test/busy_port_SUITE.erl | 6 ++-- erts/emulator/test/dirty_nif_SUITE.erl | 6 ++-- erts/emulator/test/distribution_SUITE.erl | 10 +++--- erts/emulator/test/driver_SUITE.erl | 4 +-- erts/emulator/test/erl_link_SUITE.erl | 2 +- erts/emulator/test/estone_SUITE.erl | 2 +- erts/emulator/test/float_SUITE.erl | 2 +- erts/emulator/test/long_timers_test.erl | 8 ++--- erts/emulator/test/message_queue_data_SUITE.erl | 2 +- erts/emulator/test/monitor_SUITE.erl | 2 +- erts/emulator/test/mtx_SUITE.erl | 2 +- erts/emulator/test/nif_SUITE.erl | 10 +++--- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 48 ++++++++++++------------- erts/emulator/test/node_container_SUITE.erl | 2 +- erts/emulator/test/old_scheduler_SUITE.erl | 4 +-- erts/emulator/test/port_SUITE.erl | 6 ++-- erts/emulator/test/process_SUITE.erl | 4 +-- erts/emulator/test/scheduler_SUITE.erl | 6 ++-- erts/emulator/test/signal_SUITE.erl | 2 +- erts/emulator/test/smoke_test_SUITE.erl | 2 +- erts/emulator/test/system_info_SUITE.erl | 2 +- erts/emulator/test/time_SUITE.erl | 12 +++---- erts/emulator/test/timer_bif_SUITE.erl | 14 ++++---- erts/emulator/test/trace_bif_SUITE.erl | 4 +-- erts/emulator/test/trace_call_time_SUITE.erl | 6 ++-- 27 files changed, 87 insertions(+), 87 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/after_SUITE.erl b/erts/emulator/test/after_SUITE.erl index 4f20ad3656..b1f7e06bf5 100644 --- a/erts/emulator/test/after_SUITE.erl +++ b/erts/emulator/test/after_SUITE.erl @@ -223,7 +223,7 @@ recv_after_32bit(_, _) -> blaster() -> receive {go, TimeoutTime} -> - Tmo = TimeoutTime - erlang:monotonic_time(milli_seconds), + Tmo = TimeoutTime - erlang:monotonic_time(millisecond), receive after Tmo -> ok end end. @@ -234,7 +234,7 @@ spawn_blasters(N) -> receive_after_blast(Config) when is_list(Config) -> PMs = spawn_blasters(10000), - TimeoutTime = erlang:monotonic_time(milli_seconds) + 5000, + TimeoutTime = erlang:monotonic_time(millisecond) + 5000, lists:foreach(fun ({P, _}) -> P ! {go, TimeoutTime} end, PMs), lists:foreach(fun ({P, M}) -> receive diff --git a/erts/emulator/test/alloc_SUITE.erl b/erts/emulator/test/alloc_SUITE.erl index 84cf4921d3..3a721095e2 100644 --- a/erts/emulator/test/alloc_SUITE.erl +++ b/erts/emulator/test/alloc_SUITE.erl @@ -342,7 +342,7 @@ start_node_1(Config, Opts) -> ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config)) ++ "-" - ++ integer_to_list(erlang:system_time(seconds)) + ++ integer_to_list(erlang:system_time(second)) ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))), test_server:start_node(Name, slave, [{args, Opts++" -pa "++Pa}]). diff --git a/erts/emulator/test/busy_port_SUITE.erl b/erts/emulator/test/busy_port_SUITE.erl index bb0632ae08..7094cee992 100644 --- a/erts/emulator/test/busy_port_SUITE.erl +++ b/erts/emulator/test/busy_port_SUITE.erl @@ -469,12 +469,12 @@ hs_busy_pcmd(Prt, Opts, StartFun, EndFun) -> P = spawn_link(fun () -> erlang:yield(), Tester ! {self(), doing_port_command}, - Start = erlang:monotonic_time(micro_seconds), + Start = erlang:monotonic_time(microsecond), Res = try {return, port_command(Prt, [], Opts)} catch Exception:Error -> {Exception, Error} end, - End = erlang:monotonic_time(micro_seconds), + End = erlang:monotonic_time(microsecond), Time = round((End - Start)/1000), Tester ! {self(), port_command_result, Res, Time} end), @@ -717,7 +717,7 @@ run_command(_M,spawn,{Args,Opts}) -> run_command(M,spawn,Args) -> run_command(M,spawn,{Args,[]}); run_command(Mod,Func,Args) -> - erlang:display({{Mod,Func,Args}, erlang:system_time(micro_seconds)}), + erlang:display({{Mod,Func,Args}, erlang:system_time(microsecond)}), apply(Mod,Func,Args). validate_scenario(Data,[{print,Var}|T]) -> diff --git a/erts/emulator/test/dirty_nif_SUITE.erl b/erts/emulator/test/dirty_nif_SUITE.erl index 83b098a704..c55ca7f333 100644 --- a/erts/emulator/test/dirty_nif_SUITE.erl +++ b/erts/emulator/test/dirty_nif_SUITE.erl @@ -145,9 +145,9 @@ dirty_scheduler_exit(Config) when is_list(Config) -> [ok] = mcall(Node, [fun() -> ok = erlang:load_nif(NifLib, []), - Start = erlang:monotonic_time(milli_seconds), + Start = erlang:monotonic_time(millisecond), ok = test_dirty_scheduler_exit(), - End = erlang:monotonic_time(milli_seconds), + End = erlang:monotonic_time(millisecond), io:format("Time=~p ms~n", [End-Start]), ok end]), @@ -400,7 +400,7 @@ start_node(Config, Args) when is_list(Config) -> ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config)) ++ "-" - ++ integer_to_list(erlang:system_time(seconds)) + ++ integer_to_list(erlang:system_time(second)) ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))), test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]). diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl index c6939a695d..891cb6d624 100644 --- a/erts/emulator/test/distribution_SUITE.erl +++ b/erts/emulator/test/distribution_SUITE.erl @@ -1957,7 +1957,7 @@ port_please(_Name, _Ip) -> %%% Utilities timestamp() -> - erlang:monotonic_time(milli_seconds). + erlang:monotonic_time(millisecond). start_node(X) -> start_node(X, [], []). @@ -1981,7 +1981,7 @@ start_node(Config, Args, Rel) when is_list(Config), is_list(Rel) -> ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config)) ++ "-" - ++ integer_to_list(erlang:system_time(seconds)) + ++ integer_to_list(erlang:system_time(second)) ++ "-" ++ integer_to_list(erlang:unique_integer([positive])))), start_node(Name, Args, Rel). @@ -2100,7 +2100,7 @@ node_monitor(Master) -> Master ! {nodeup, node(), Node} end, Nodes0), - io:format("~p ~p: ~p~n", [node(), erlang:system_time(micro_seconds), Nodes0]), + io:format("~p ~p: ~p~n", [node(), erlang:system_time(microsecond), Nodes0]), node_monitor_loop(Master); false -> net_kernel:monitor_nodes(false, Opts), @@ -2121,7 +2121,7 @@ node_monitor_loop(Master) -> receive {nodeup, Node, _InfoList} = Msg -> Master ! {nodeup, node(), Node}, - io:format("~p ~p: ~p~n", [node(), erlang:system_time(micro_seconds), Msg]), + io:format("~p ~p: ~p~n", [node(), erlang:system_time(microsecond), Msg]), node_monitor_loop(Master); {nodedown, Node, InfoList} = Msg -> Reason = case lists:keysearch(nodedown_reason, 1, InfoList) of @@ -2129,7 +2129,7 @@ node_monitor_loop(Master) -> _ -> undefined end, Master ! {nodedown, node(), Node, Reason}, - io:format("~p ~p: ~p~n", [node(), erlang:system_time(micro_seconds), Msg]), + io:format("~p ~p: ~p~n", [node(), erlang:system_time(microsecond), Msg]), node_monitor_loop(Master) end. diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl index f134a197aa..a751fd251e 100644 --- a/erts/emulator/test/driver_SUITE.erl +++ b/erts/emulator/test/driver_SUITE.erl @@ -2427,7 +2427,7 @@ erl_millisecs() -> erl_millisecs(erlang:monotonic_time()). erl_millisecs(MonotonicTime) -> - (1000*MonotonicTime)/erlang:convert_time_unit(1,seconds,native). + (1000*MonotonicTime)/erlang:convert_time_unit(1,second,native). %% Start/stop drivers. start_driver(Config, Name, Binary) -> @@ -2481,7 +2481,7 @@ start_node(Config) when is_list(Config) -> ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config)) ++ "-" - ++ integer_to_list(erlang:system_time(seconds)) + ++ integer_to_list(erlang:system_time(second)) ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))), test_server:start_node(Name, slave, [{args, "-pa "++Pa}]). diff --git a/erts/emulator/test/erl_link_SUITE.erl b/erts/emulator/test/erl_link_SUITE.erl index 93d2065ba3..89e1aefb50 100644 --- a/erts/emulator/test/erl_link_SUITE.erl +++ b/erts/emulator/test/erl_link_SUITE.erl @@ -1011,7 +1011,7 @@ get_names(N, T, Acc) -> ++ "-" ++ atom_to_list(T) ++ "-" - ++ integer_to_list(erlang:system_time(seconds)) + ++ integer_to_list(erlang:system_time(second)) ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))) | Acc]). diff --git a/erts/emulator/test/estone_SUITE.erl b/erts/emulator/test/estone_SUITE.erl index 1180a45585..3ce849b88e 100644 --- a/erts/emulator/test/estone_SUITE.erl +++ b/erts/emulator/test/estone_SUITE.erl @@ -364,7 +364,7 @@ monotonic_time() -> try erlang:monotonic_time() catch error:undef -> erlang:now() end. subtr(Before, After) when is_integer(Before), is_integer(After) -> - erlang:convert_time_unit(After-Before, native, micro_seconds); + erlang:convert_time_unit(After-Before, native, microsecond); subtr({_,_,_}=Before, {_,_,_}=After) -> timer:now_diff(After, Before). diff --git a/erts/emulator/test/float_SUITE.erl b/erts/emulator/test/float_SUITE.erl index e85addae3a..36b1f9179f 100644 --- a/erts/emulator/test/float_SUITE.erl +++ b/erts/emulator/test/float_SUITE.erl @@ -276,7 +276,7 @@ start_node(Config) when is_list(Config) -> ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config)) ++ "-" - ++ integer_to_list(erlang:system_time(seconds)) + ++ integer_to_list(erlang:system_time(second)) ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))), test_server:start_node(Name, slave, [{args, "-pa "++Pa}]). diff --git a/erts/emulator/test/long_timers_test.erl b/erts/emulator/test/long_timers_test.erl index 7c055a31f9..0f211bce69 100644 --- a/erts/emulator/test/long_timers_test.erl +++ b/erts/emulator/test/long_timers_test.erl @@ -113,7 +113,7 @@ check([#timeout_rec{timeout = Timeout, [type_str(Type), time_str(Timeout), SuccessStr, - time_str(TimeoutDiff, erlang:convert_time_unit(1, seconds, native))]), + time_str(TimeoutDiff, erlang:convert_time_unit(1, second, native))]), check(TORs, NeedRes, NewOk); check([], _NeedRes, Ok) -> Ok. @@ -143,13 +143,13 @@ unit_str(Res) -> Res. to_diff(Timeout, Start, Stop) -> %% 'Timeout' in milli seconds %% 'Start', 'Stop', and result in native unit - (Stop - Start) - erlang:convert_time_unit(Timeout, milli_seconds, native). + (Stop - Start) - erlang:convert_time_unit(Timeout, millisecond, native). ms(Time) -> - erlang:convert_time_unit(Time, native, milli_seconds). + erlang:convert_time_unit(Time, native, millisecond). max_late() -> - erlang:convert_time_unit(?MAX_LATE_MS, milli_seconds, native). + erlang:convert_time_unit(?MAX_LATE_MS, millisecond, native). receive_after(Timeout) -> Start = erlang:monotonic_time(), diff --git a/erts/emulator/test/message_queue_data_SUITE.erl b/erts/emulator/test/message_queue_data_SUITE.erl index 44e77dfad0..e084b9482d 100644 --- a/erts/emulator/test/message_queue_data_SUITE.erl +++ b/erts/emulator/test/message_queue_data_SUITE.erl @@ -200,7 +200,7 @@ start_node(Config, Opts) when is_list(Config), is_list(Opts) -> ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config)) ++ "-" - ++ integer_to_list(erlang:system_time(seconds)) + ++ integer_to_list(erlang:system_time(second)) ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))), test_server:start_node(Name, slave, [{args, Opts++" -pa "++Pa}]). diff --git a/erts/emulator/test/monitor_SUITE.erl b/erts/emulator/test/monitor_SUITE.erl index 90d2bd8c5d..827ed817cc 100644 --- a/erts/emulator/test/monitor_SUITE.erl +++ b/erts/emulator/test/monitor_SUITE.erl @@ -697,7 +697,7 @@ mixer(Config) when is_list(Config) -> named_down(Config) when is_list(Config) -> Name = list_to_atom(atom_to_list(?MODULE) ++ "-named_down-" - ++ integer_to_list(erlang:system_time(seconds)) + ++ integer_to_list(erlang:system_time(second)) ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))), Prio = process_flag(priority,high), %% Spawn a bunch of high prio cpu bound processes to prevent diff --git a/erts/emulator/test/mtx_SUITE.erl b/erts/emulator/test/mtx_SUITE.erl index 1493e52655..12928ed6d8 100644 --- a/erts/emulator/test/mtx_SUITE.erl +++ b/erts/emulator/test/mtx_SUITE.erl @@ -443,7 +443,7 @@ hammer_ets_rwlock_test(XOpts, UW, C, N, NP, SC) -> {'DOWN', M, process, P, _} -> ok end end, Ps), - Res = (Stop-Start)/erlang:convert_time_unit(1,seconds,native), + Res = (Stop-Start)/erlang:convert_time_unit(1,second,native), Caller ! {?MODULE, self(), Res} end, TP = spawn_link(T), diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index a0e9f1bad6..a5fe4e8fec 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -1692,7 +1692,7 @@ nif_raise_exceptions(NifFunc) -> end, ok, ExcTerms). -define(ERL_NIF_TIME_ERROR, -9223372036854775808). --define(TIME_UNITS, [seconds, milli_seconds, micro_seconds, nano_seconds]). +-define(TIME_UNITS, [second, millisecond, microsecond, nanosecond]). nif_monotonic_time(Config) -> ?ERL_NIF_TIME_ERROR = monotonic_time(invalid_time_unit), @@ -1758,8 +1758,8 @@ chk_toffs([TU|TUs]) -> chk_toffs(TUs). nif_convert_time_unit(Config) -> - ?ERL_NIF_TIME_ERROR = convert_time_unit(0, seconds, invalid_time_unit), - ?ERL_NIF_TIME_ERROR = convert_time_unit(0, invalid_time_unit, seconds), + ?ERL_NIF_TIME_ERROR = convert_time_unit(0, second, invalid_time_unit), + ?ERL_NIF_TIME_ERROR = convert_time_unit(0, invalid_time_unit, second), ?ERL_NIF_TIME_ERROR = convert_time_unit(0, invalid_time_unit, invalid_time_unit), lists:foreach(fun (Offset) -> lists:foreach(fun (Diff) -> @@ -1808,7 +1808,7 @@ nif_convert_time_unit(Config) -> ctu_loop(0) -> ok; ctu_loop(N) -> - chk_ctu(erlang:monotonic_time(nano_seconds)), + chk_ctu(erlang:monotonic_time(nanosecond)), ctu_loop(N-1). chk_ctu(Time) -> @@ -1823,7 +1823,7 @@ chk_ctu(Time, [FromTU|FromTUs]) -> chk_ctu(_Time, _FromTU, []) -> ok; chk_ctu(Time, FromTU, [ToTU|ToTUs]) -> - T = erlang:convert_time_unit(Time, nano_seconds, FromTU), + T = erlang:convert_time_unit(Time, nanosecond, FromTU), TE = erlang:convert_time_unit(T, FromTU, ToTU), TN = convert_time_unit(T, FromTU, ToTU), case TE =:= TN of diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 13846244d4..f2b1ef9d24 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -38,10 +38,10 @@ static ERL_NIF_TERM atom_self; static ERL_NIF_TERM atom_ok; static ERL_NIF_TERM atom_join; static ERL_NIF_TERM atom_binary_resource_type; -static ERL_NIF_TERM atom_seconds; -static ERL_NIF_TERM atom_milli_seconds; -static ERL_NIF_TERM atom_micro_seconds; -static ERL_NIF_TERM atom_nano_seconds; +static ERL_NIF_TERM atom_second; +static ERL_NIF_TERM atom_millisecond; +static ERL_NIF_TERM atom_microsecond; +static ERL_NIF_TERM atom_nanosecond; typedef struct @@ -147,10 +147,10 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_ok = enif_make_atom(env,"ok"); atom_join = enif_make_atom(env,"join"); atom_binary_resource_type = enif_make_atom(env,"binary_resource_type"); - atom_seconds = enif_make_atom(env,"seconds"); - atom_milli_seconds = enif_make_atom(env,"milli_seconds"); - atom_micro_seconds = enif_make_atom(env,"micro_seconds"); - atom_nano_seconds = enif_make_atom(env,"nano_seconds"); + atom_second = enif_make_atom(env,"second"); + atom_millisecond = enif_make_atom(env,"millisecond"); + atom_microsecond = enif_make_atom(env,"microsecond"); + atom_nanosecond = enif_make_atom(env,"nanosecond"); *priv_data = data; return 0; @@ -1808,13 +1808,13 @@ static ERL_NIF_TERM monotonic_time(ErlNifEnv* env, int argc, const ERL_NIF_TERM if (argc != 1) return atom_false; - if (enif_compare(argv[0], atom_seconds) == 0) + if (enif_compare(argv[0], atom_second) == 0) time_unit = ERL_NIF_SEC; - else if (enif_compare(argv[0], atom_milli_seconds) == 0) + else if (enif_compare(argv[0], atom_millisecond) == 0) time_unit = ERL_NIF_MSEC; - else if (enif_compare(argv[0], atom_micro_seconds) == 0) + else if (enif_compare(argv[0], atom_microsecond) == 0) time_unit = ERL_NIF_USEC; - else if (enif_compare(argv[0], atom_nano_seconds) == 0) + else if (enif_compare(argv[0], atom_nanosecond) == 0) time_unit = ERL_NIF_NSEC; else time_unit = 4711; /* invalid time unit */ @@ -1829,13 +1829,13 @@ static ERL_NIF_TERM time_offset(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg if (argc != 1) return atom_false; - if (enif_compare(argv[0], atom_seconds) == 0) + if (enif_compare(argv[0], atom_second) == 0) time_unit = ERL_NIF_SEC; - else if (enif_compare(argv[0], atom_milli_seconds) == 0) + else if (enif_compare(argv[0], atom_millisecond) == 0) time_unit = ERL_NIF_MSEC; - else if (enif_compare(argv[0], atom_micro_seconds) == 0) + else if (enif_compare(argv[0], atom_microsecond) == 0) time_unit = ERL_NIF_USEC; - else if (enif_compare(argv[0], atom_nano_seconds) == 0) + else if (enif_compare(argv[0], atom_nanosecond) == 0) time_unit = ERL_NIF_NSEC; else time_unit = 4711; /* invalid time unit */ @@ -1856,24 +1856,24 @@ static ERL_NIF_TERM convert_time_unit(ErlNifEnv* env, int argc, const ERL_NIF_TE val = (ErlNifTime) i64; - if (enif_compare(argv[1], atom_seconds) == 0) + if (enif_compare(argv[1], atom_second) == 0) from = ERL_NIF_SEC; - else if (enif_compare(argv[1], atom_milli_seconds) == 0) + else if (enif_compare(argv[1], atom_millisecond) == 0) from = ERL_NIF_MSEC; - else if (enif_compare(argv[1], atom_micro_seconds) == 0) + else if (enif_compare(argv[1], atom_microsecond) == 0) from = ERL_NIF_USEC; - else if (enif_compare(argv[1], atom_nano_seconds) == 0) + else if (enif_compare(argv[1], atom_nanosecond) == 0) from = ERL_NIF_NSEC; else from = 4711; /* invalid time unit */ - if (enif_compare(argv[2], atom_seconds) == 0) + if (enif_compare(argv[2], atom_second) == 0) to = ERL_NIF_SEC; - else if (enif_compare(argv[2], atom_milli_seconds) == 0) + else if (enif_compare(argv[2], atom_millisecond) == 0) to = ERL_NIF_MSEC; - else if (enif_compare(argv[2], atom_micro_seconds) == 0) + else if (enif_compare(argv[2], atom_microsecond) == 0) to = ERL_NIF_USEC; - else if (enif_compare(argv[2], atom_nano_seconds) == 0) + else if (enif_compare(argv[2], atom_nanosecond) == 0) to = ERL_NIF_NSEC; else to = 4711; /* invalid time unit */ diff --git a/erts/emulator/test/node_container_SUITE.erl b/erts/emulator/test/node_container_SUITE.erl index 536c91d4ae..af18545bff 100644 --- a/erts/emulator/test/node_container_SUITE.erl +++ b/erts/emulator/test/node_container_SUITE.erl @@ -1092,7 +1092,7 @@ wait_until(Pred) -> get_nodefirstname_string() -> atom_to_list(?MODULE) ++ "-" - ++ integer_to_list(erlang:system_time(seconds)) + ++ integer_to_list(erlang:system_time(second)) ++ "-" ++ integer_to_list(erlang:unique_integer([positive])). diff --git a/erts/emulator/test/old_scheduler_SUITE.erl b/erts/emulator/test/old_scheduler_SUITE.erl index f91d84beea..ffe7d40139 100644 --- a/erts/emulator/test/old_scheduler_SUITE.erl +++ b/erts/emulator/test/old_scheduler_SUITE.erl @@ -309,13 +309,13 @@ receiver(T0, TimeSec, Main, {P1,P1N}, {P2,P2N}) -> %% uncomment lines below to get life sign (debug) receiver(T0, Time, Main, P1,P1N,P1Rs, P2,P2N,P2Rs, 0) -> - % T = erlang:convert_time_unit(erlang:monotonic_time() - T0, native, milli_seconds), + % T = erlang:convert_time_unit(erlang:monotonic_time() - T0, native, millisecond), % erlang:display({round(T/1000),P1Rs,P2Rs}), receiver(T0, Time, Main, P1,P1N,P1Rs, P2,P2N,P2Rs, 100000); receiver(T0, Time, Main, P1,P1N,P1Rs, P2,P2N,P2Rs, C) -> Remain = Time - erlang:convert_time_unit(erlang:monotonic_time() - T0, - native, milli_seconds), % test time remaining + native, millisecond), % test time remaining Remain1 = if Remain < 0 -> 0; true -> diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index ee07699884..51e0c5d92f 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -1867,7 +1867,7 @@ exit_status_msb_test(Config, SleepSecs) when is_list(Config) -> Parent = self(), io:format("SleepSecs = ~p~n", [SleepSecs]), PortProg = "sleep " ++ integer_to_list(SleepSecs), - Start = erlang:monotonic_time(micro_seconds), + Start = erlang:monotonic_time(microsecond), NoProcs = case NoSchedsOnln of NProcs when NProcs < ?EXIT_STATUS_MSB_MAX_PROCS -> NProcs; @@ -1941,12 +1941,12 @@ exit_status_msb_test(Config, SleepSecs) when is_list(Config) -> receive {P, started, SIds} -> SIds end end, Procs), - StartedTime = (erlang:monotonic_time(micro_seconds) - Start)/1000000, + StartedTime = (erlang:monotonic_time(microsecond) - Start)/1000000, io:format("StartedTime = ~p~n", [StartedTime]), true = StartedTime < SleepSecs, erlang:system_flag(multi_scheduling, block), lists:foreach(fun (P) -> receive {P, done} -> ok end end, Procs), - DoneTime = (erlang:monotonic_time(micro_seconds) - Start)/1000000, + DoneTime = (erlang:monotonic_time(microsecond) - Start)/1000000, io:format("DoneTime = ~p~n", [DoneTime]), true = DoneTime > SleepSecs, ok = verify_multi_scheduling_blocked(), diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index dae8990f56..8428a0ffd3 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -372,7 +372,7 @@ eat_high(Low) -> process_flag(priority, high), receive after 1000 -> ok end, exit(Low, {you, are, dead}), - loop(erlang:monotonic_time() + erlang:convert_time_unit(5,seconds,native)). + loop(erlang:monotonic_time() + erlang:convert_time_unit(5,second,native)). %% Busy loop for 5 seconds. @@ -2567,7 +2567,7 @@ start_node(Config, Args) when is_list(Config) -> ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config)) ++ "-" - ++ integer_to_list(erlang:system_time(seconds)) + ++ integer_to_list(erlang:system_time(second)) ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))), test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]). diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl index f18d79d770..b44ee45da9 100644 --- a/erts/emulator/test/scheduler_SUITE.erl +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -1978,10 +1978,10 @@ do_it(Tracer, Low, Normal, High, Max) -> do_it(Tracer, Low, Normal, High, Max, RedsPerSchedLimit) -> OldPrio = process_flag(priority, max), go_work(Low, Normal, High, Max), - StartWait = erlang:monotonic_time(milli_seconds), + StartWait = erlang:monotonic_time(millisecond), %% Give the emulator a chance to balance the load... wait_balance(5), - EndWait = erlang:monotonic_time(milli_seconds), + EndWait = erlang:monotonic_time(millisecond), BalanceWait = EndWait-StartWait, erlang:display({balance_wait, BalanceWait}), Timeout = (15 - 4)*60*1000 - BalanceWait, @@ -2181,7 +2181,7 @@ start_node(Config, Args) when is_list(Config) -> ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config)) ++ "-" - ++ integer_to_list(erlang:system_time(seconds)) + ++ integer_to_list(erlang:system_time(second)) ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))), test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]). diff --git a/erts/emulator/test/signal_SUITE.erl b/erts/emulator/test/signal_SUITE.erl index 0b11fa13f5..7e516176f7 100644 --- a/erts/emulator/test/signal_SUITE.erl +++ b/erts/emulator/test/signal_SUITE.erl @@ -484,7 +484,7 @@ repeat(Fun, N) when is_integer(N) -> start_node(Config) -> Name = list_to_atom(atom_to_list(?MODULE) ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config)) - ++ "-" ++ integer_to_list(erlang:system_time(seconds)) + ++ "-" ++ integer_to_list(erlang:system_time(second)) ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))), Pa = filename:dirname(code:which(?MODULE)), test_server:start_node(Name, slave, [{args, "-pa " ++ Pa}]). diff --git a/erts/emulator/test/smoke_test_SUITE.erl b/erts/emulator/test/smoke_test_SUITE.erl index 042c7225d5..5eccdc562b 100644 --- a/erts/emulator/test/smoke_test_SUITE.erl +++ b/erts/emulator/test/smoke_test_SUITE.erl @@ -152,7 +152,7 @@ start_node(Config, Args) when is_list(Config) -> ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config)) ++ "-" - ++ integer_to_list(erlang:system_time(seconds)) + ++ integer_to_list(erlang:system_time(second)) ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))), Opts = [{args, "-pa "++Pa++" "++Args}], diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl index f31d474c20..a4aedb31f6 100644 --- a/erts/emulator/test/system_info_SUITE.erl +++ b/erts/emulator/test/system_info_SUITE.erl @@ -508,7 +508,7 @@ start_node(Config, Envs) when is_list(Config) -> ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config)) ++ "-" - ++ integer_to_list(erlang:system_time(seconds)) + ++ integer_to_list(erlang:system_time(second)) ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))), test_server:start_node(Name, peer, [{args, "-pa "++Pa}, {env, Envs}]). diff --git a/erts/emulator/test/time_SUITE.erl b/erts/emulator/test/time_SUITE.erl index 87b8c62cfa..9501569814 100644 --- a/erts/emulator/test/time_SUITE.erl +++ b/erts/emulator/test/time_SUITE.erl @@ -295,7 +295,7 @@ timestamp(Config) when is_list(Config) -> os_system_time_offset() -> erlang:convert_time_unit(os:system_time() - erlang:monotonic_time(), - native, micro_seconds). + native, microsecond). had_time_warp(Secs) -> had_time_warp(os_system_time_offset(), Secs). @@ -488,12 +488,12 @@ check_time_warp_mode(Config, TimeCorrection, TimeWarpMode) -> MonotonicTimeUnit = rpc:call(Node, erlang, convert_time_unit, - [1, seconds, native]), + [1, second, native]), UpMilliSeconds = erlang:convert_time_unit(MonotonicTime - StartTime, MonotonicTimeUnit, - milli_seconds), + millisecond), io:format("UpMilliSeconds=~p~n", [UpMilliSeconds]), - End = erlang:monotonic_time(milli_seconds), + End = erlang:monotonic_time(millisecond), stop_node(Node), try true = (UpMilliSeconds > (98*MonotonicityTimeout) div 100), @@ -810,10 +810,10 @@ do_check_erlang_timestamp(Done, Mon, TO) -> MaxMon = erlang:monotonic_time(), TsMin = erlang:convert_time_unit(MinMon+TO, native, - micro_seconds), + microsecond), TsMax = erlang:convert_time_unit(MaxMon+TO, native, - micro_seconds), + microsecond), TsTime = (MegaSec*1000000+Sec)*1000000+MicroSec, case (TsMin =< TsTime) andalso (TsTime =< TsMax) of true -> diff --git a/erts/emulator/test/timer_bif_SUITE.erl b/erts/emulator/test/timer_bif_SUITE.erl index a5f11bd959..404a1cd562 100644 --- a/erts/emulator/test/timer_bif_SUITE.erl +++ b/erts/emulator/test/timer_bif_SUITE.erl @@ -489,7 +489,7 @@ registered_process(Config) when is_list(Config) -> same_time_yielding(Config) when is_list(Config) -> Mem = mem(), SchdlrsOnln = erlang:system_info(schedulers_online), - Tmo = erlang:monotonic_time(milli_seconds) + 3000, + Tmo = erlang:monotonic_time(millisecond) + 3000, Tmrs = lists:map(fun (I) -> process_flag(scheduler, (I rem SchdlrsOnln) + 1), erlang:start_timer(Tmo, self(), hej, [{abs, true}]) @@ -497,7 +497,7 @@ same_time_yielding(Config) when is_list(Config) -> lists:seq(1, (?TIMEOUT_YIELD_LIMIT*3+1)*SchdlrsOnln)), true = mem_larger_than(Mem), lists:foreach(fun (Tmr) -> receive {timeout, Tmr, hej} -> ok end end, Tmrs), - Done = erlang:monotonic_time(milli_seconds), + Done = erlang:monotonic_time(millisecond), true = Done >= Tmo, case erlang:system_info(build_type) of opt -> true = Done < Tmo + 200; @@ -517,10 +517,10 @@ same_time_yielding_with_cancel_other(Config) when is_list(Config) -> do_cancel_tmrs(Tmo, Tmrs, Tester) -> BeginCancel = erlang:convert_time_unit(Tmo, - milli_seconds, - micro_seconds) - 100, + millisecond, + microsecond) - 100, busy_wait_until(fun () -> - erlang:monotonic_time(micro_seconds) >= BeginCancel + erlang:monotonic_time(microsecond) >= BeginCancel end), lists:foreach(fun (Tmr) -> erlang:cancel_timer(Tmr, @@ -535,7 +535,7 @@ do_cancel_tmrs(Tmo, Tmrs, Tester) -> same_time_yielding_with_cancel_test(Other, Accessor) -> Mem = mem(), SchdlrsOnln = erlang:system_info(schedulers_online), - Tmo = erlang:monotonic_time(milli_seconds) + 3000, + Tmo = erlang:monotonic_time(millisecond) + 3000, Tester = self(), Cancelor = case Other of false -> @@ -656,7 +656,7 @@ get_msg() -> start_slave() -> Pa = filename:dirname(code:which(?MODULE)), Name = atom_to_list(?MODULE) - ++ "-" ++ integer_to_list(erlang:system_time(seconds)) + ++ "-" ++ integer_to_list(erlang:system_time(second)) ++ "-" ++ integer_to_list(erlang:unique_integer([positive])), {ok, Node} = test_server:start_node(Name, slave, [{args, "-pa " ++ Pa}]), Node. diff --git a/erts/emulator/test/trace_bif_SUITE.erl b/erts/emulator/test/trace_bif_SUITE.erl index 491b37ae46..f60c777ba1 100644 --- a/erts/emulator/test/trace_bif_SUITE.erl +++ b/erts/emulator/test/trace_bif_SUITE.erl @@ -289,9 +289,9 @@ receive_trace_msg_ts_return_to({trace_ts, Pid, return_to, {M,F,A}}, PrevTs, TsTy make_ts(timestamp) -> erlang:now(); make_ts(monotonic_timestamp) -> - erlang:monotonic_time(nano_seconds); + erlang:monotonic_time(nanosecond); make_ts(strict_monotonic_timestamp) -> - MT = erlang:monotonic_time(nano_seconds), + MT = erlang:monotonic_time(nanosecond), UMI = erlang:unique_integer([monotonic]), {MT, UMI}. diff --git a/erts/emulator/test/trace_call_time_SUITE.erl b/erts/emulator/test/trace_call_time_SUITE.erl index 6582ad134b..26f96a1766 100644 --- a/erts/emulator/test/trace_call_time_SUITE.erl +++ b/erts/emulator/test/trace_call_time_SUITE.erl @@ -294,7 +294,7 @@ combo(Config) when is_list(Config) -> T0 = erlang:monotonic_time(), with_bif(Nbc), T1 = erlang:monotonic_time(), - TimeB = erlang:convert_time_unit(T1-T0, native, micro_seconds), + TimeB = erlang:convert_time_unit(T1-T0, native, microsecond), %% List = collect(100), @@ -655,13 +655,13 @@ execute(Pids, Mfa) when is_list(Pids) -> [P ! {self(), execute, Mfa} || P <- Pids], As = [receive {P, answer, Answer} -> Answer end || P <- Pids], T1 = erlang:monotonic_time(), - {As, erlang:convert_time_unit(T1-T0, native, micro_seconds)}; + {As, erlang:convert_time_unit(T1-T0, native, microsecond)}; execute(P, Mfa) -> T0 = erlang:monotonic_time(), P ! {self(), execute, Mfa}, A = receive {P, answer, Answer} -> Answer end, T1 = erlang:monotonic_time(), - {A, erlang:convert_time_unit(T1-T0, native, micro_seconds)}. + {A, erlang:convert_time_unit(T1-T0, native, microsecond)}. -- cgit v1.2.3 From 9d0638216d35ca0f21c1eea20f8daa3992ac4f71 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Tue, 2 Aug 2016 15:58:06 +0200 Subject: Fix purge of code Ensure that we cannot get any dangling pointers into code that has been purged. This is done by a two phase purge. At first phase all fun entries pointing into the code to purge are marked for purge. All processes trying to call these funs will be suspended and by this we avoid getting new direct references into the code. When all processes has been checked, these processes are resumed. The new purge strategy now also completely ignore the existence of indirect references to the code (funs). If such exist, they will cause bad fun exceptions to the caller, but will not prevent a soft purge or cause a kill of a process having such live references during a hard purge. This since it is impossible to give any guarantees that no processes in the system have such indirect references. Even when the system is completely clean from such references, new ones can appear via distribution and/or disk. --- erts/emulator/test/code_SUITE.erl | 223 ++++++++++++++++++++- .../emulator/test/code_SUITE_data/my_code_test.erl | 2 - .../test/code_SUITE_data/my_code_test2.erl | 32 +++ 3 files changed, 244 insertions(+), 13 deletions(-) create mode 100644 erts/emulator/test/code_SUITE_data/my_code_test2.erl (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index 2347a3d4ef..34515efa3d 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -20,7 +20,8 @@ -module(code_SUITE). -export([all/0, suite/0, init_per_suite/1, end_per_suite/1, - versions/1,new_binary_types/1, + versions/1,new_binary_types/1, call_purged_fun_code_gone/1, + call_purged_fun_code_reload/1, call_purged_fun_code_there/1, t_check_process_code/1,t_check_old_code/1, t_check_process_code_ets/1, external_fun/1,get_chunk/1,module_md5/1,make_stub/1, @@ -34,7 +35,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [versions, new_binary_types, t_check_process_code, + [versions, new_binary_types, call_purged_fun_code_gone, + call_purged_fun_code_reload, call_purged_fun_code_there, t_check_process_code, t_check_process_code_ets, t_check_old_code, external_fun, get_chunk, module_md5, make_stub, make_stub_many_funs, constant_pools, constant_refc_binaries, false_dependency, @@ -127,12 +129,169 @@ new_binary_types(Config) when is_list(Config) -> bit_sized_binary(Bin))), ok. +call_purged_fun_code_gone(Config) when is_list(Config) -> + Priv = proplists:get_value(priv_dir, Config), + Data = proplists:get_value(data_dir, Config), + call_purged_fun_test(Priv, Data, code_gone), + ok. + +call_purged_fun_code_reload(Config) when is_list(Config) -> + Priv = proplists:get_value(priv_dir, Config), + Data = proplists:get_value(data_dir, Config), + Path = code:get_path(), + true = code:add_path(Priv), + try + call_purged_fun_test(Priv, Data, code_reload) + after + code:set_path(Path) + end, + ok. + +call_purged_fun_code_there(Config) when is_list(Config) -> + Priv = proplists:get_value(priv_dir, Config), + Data = proplists:get_value(data_dir, Config), + call_purged_fun_test(Priv, Data, code_there), + ok. + +call_purged_fun_test(Priv, Data, Type) -> + File = filename:join(Data, "my_code_test2"), + Code = filename:join(Priv, "my_code_test2"), + + catch erlang:purge_module(my_code_test2), + catch erlang:delete_module(my_code_test2), + catch erlang:purge_module(my_code_test2), + + {ok,my_code_test2} = c:c(File, [{outdir,Priv}]), + + T = ets:new(my_code_test2_fun_table, []), + ets:insert(T, {my_fun,my_code_test2:make_fun(4711)}), + ets:insert(T, {my_fun2,my_code_test2:make_fun2()}), + + spawn(fun () -> + [{my_fun2,F2}] = ets:lookup(T, my_fun2), + F2(fun () -> + receive after infinity -> ok end + end, + fun () -> ok end), + exit(completed) + end), + + PurgeType = case Type of + code_gone -> + ok = file:delete(Code++".beam"), + true; + code_reload -> + true; + code_there -> + false + end, + + true = erlang:delete_module(my_code_test2), + + Purge = start_purge(my_code_test2, PurgeType), + + {P0, M0} = spawn_monitor(fun () -> + [{my_fun,F}] = ets:lookup(T, my_fun), + 4712 = F(1), + exit(completed) + end), + + wait_until(fun () -> + {status, suspended} + == process_info(P0, status) + end), + + ok = continue_purge(Purge), + + {P1, M1} = spawn_monitor(fun () -> + [{my_fun,F}] = ets:lookup(T, my_fun), + 4713 = F(2), + exit(completed) + end), + {P2, M2} = spawn_monitor(fun () -> + [{my_fun,F}] = ets:lookup(T, my_fun), + 4714 = F(3), + exit(completed) + end), + + wait_until(fun () -> + {status, suspended} + == process_info(P1, status) + end), + wait_until(fun () -> + {status, suspended} + == process_info(P2, status) + end), + + {current_function, + {erts_code_purger, + pending_purge_lambda, + 3}} = process_info(P0, current_function), + {current_function, + {erts_code_purger, + pending_purge_lambda, + 3}} = process_info(P1, current_function), + {current_function, + {erts_code_purger, + pending_purge_lambda, + 3}} = process_info(P2, current_function), + + case Type of + code_there -> + false = complete_purge(Purge); + _ -> + {true, true} = complete_purge(Purge) + end, + + case Type of + code_gone -> + receive + {'DOWN', M0, process, P0, Reason0} -> + {undef, _} = Reason0 + end, + receive + {'DOWN', M1, process, P1, Reason1} -> + {undef, _} = Reason1 + end, + receive + {'DOWN', M2, process, P2, Reason2} -> + {undef, _} = Reason2 + end; + _ -> + receive + {'DOWN', M0, process, P0, Reason0} -> + completed = Reason0 + end, + receive + {'DOWN', M1, process, P1, Reason1} -> + completed = Reason1 + end, + receive + {'DOWN', M2, process, P2, Reason2} -> + completed = Reason2 + end, + catch erlang:purge_module(my_code_test2), + catch erlang:delete_module(my_code_test2), + catch erlang:purge_module(my_code_test2) + end, + ok. + t_check_process_code(Config) when is_list(Config) -> + case check_process_code_handle(indirect_references) of + false -> {skipped, "check_process_code() ignores funs"}; + true -> t_check_process_code_test(Config) + end. + +t_check_process_code_test(Config) -> Priv = proplists:get_value(priv_dir, Config), Data = proplists:get_value(data_dir, Config), File = filename:join(Data, "my_code_test"), Code = filename:join(Priv, "my_code_test"), + catch erlang:purge_module(my_code_test), + catch erlang:delete_module(my_code_test), + catch erlang:purge_module(my_code_test), + {ok,my_code_test} = c:c(File, [{outdir,Priv}]), MyFun = fun(X, Y) -> X + Y end, %Confuse things. @@ -231,11 +390,16 @@ gc1() -> ok. %% Test check_process_code/2 in combination with a fun obtained from an ets table. t_check_process_code_ets(Config) when is_list(Config) -> - case test_server:is_native(?MODULE) of - true -> - {skip,"Native code"}; - false -> - do_check_process_code_ets(Config) + case check_process_code_handle(indirect_references) of + false -> + {skipped, "check_process_code() ignores funs"}; + true -> + case test_server:is_native(?MODULE) of + true -> + {skip,"Native code"}; + false -> + do_check_process_code_ets(Config) + end end. do_check_process_code_ets(Config) -> @@ -243,8 +407,9 @@ do_check_process_code_ets(Config) -> Data = proplists:get_value(data_dir, Config), File = filename:join(Data, "my_code_test"), - erlang:purge_module(my_code_test), - erlang:delete_module(my_code_test), + catch erlang:purge_module(my_code_test), + catch erlang:delete_module(my_code_test), + catch erlang:purge_module(my_code_test), {ok,my_code_test} = c:c(File, [{outdir,Priv}]), T = ets:new(my_code_test, []), @@ -295,8 +460,8 @@ t_check_old_code(Config) when is_list(Config) -> Data = proplists:get_value(data_dir, Config), File = filename:join(Data, "my_code_test"), - erlang:purge_module(my_code_test), - erlang:delete_module(my_code_test), + catch erlang:purge_module(my_code_test), + catch erlang:delete_module(my_code_test), catch erlang:purge_module(my_code_test), false = erlang:check_old_code(my_code_test), @@ -971,3 +1136,39 @@ flush() -> receive _ -> flush() after 0 -> ok end. id(I) -> I. + +check_process_code_handle(What) -> + lists:member(What, erlang:system_info(check_process_code)). + +wait_until(Fun) -> + case Fun() of + true -> + ok; + false -> + receive after 100 -> ok end, + wait_until(Fun) + end. + +start_purge(Mod, Type) when is_atom(Mod) + andalso ((Type == true) + orelse (Type == false)) -> + Ref = make_ref(), + erts_code_purger ! {test_purge, Mod, self(), Type, Ref}, + receive + {started, Ref} -> + Ref + end. + +continue_purge(Ref) when is_reference(Ref) -> + erts_code_purger ! {continue, Ref}, + receive + {continued, Ref} -> + ok + end. + +complete_purge(Ref) when is_reference(Ref) -> + erts_code_purger ! {complete, Ref}, + receive + {test_purge, Res, Ref} -> + Res + end. diff --git a/erts/emulator/test/code_SUITE_data/my_code_test.erl b/erts/emulator/test/code_SUITE_data/my_code_test.erl index d2386157d6..9d12aa9897 100644 --- a/erts/emulator/test/code_SUITE_data/my_code_test.erl +++ b/erts/emulator/test/code_SUITE_data/my_code_test.erl @@ -24,5 +24,3 @@ make_fun(A) -> fun(X) -> A + X end. - - diff --git a/erts/emulator/test/code_SUITE_data/my_code_test2.erl b/erts/emulator/test/code_SUITE_data/my_code_test2.erl new file mode 100644 index 0000000000..57973535d4 --- /dev/null +++ b/erts/emulator/test/code_SUITE_data/my_code_test2.erl @@ -0,0 +1,32 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +-module(my_code_test2). + +-export([make_fun/1, make_fun2/0]). + +make_fun(A) -> + fun(X) -> A + X end. + +make_fun2() -> + fun (F1,F2) -> + F1(), + F2() + end. -- cgit v1.2.3 From 0e04e76df2ea71e2e2e116afef04c497d84b1024 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Mon, 8 Aug 2016 17:13:24 +0200 Subject: Perform check_process_code while process is executing dirty --- erts/emulator/test/dirty_nif_SUITE.erl | 75 +++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/dirty_nif_SUITE.erl b/erts/emulator/test/dirty_nif_SUITE.erl index 83b098a704..c2d2e58957 100644 --- a/erts/emulator/test/dirty_nif_SUITE.erl +++ b/erts/emulator/test/dirty_nif_SUITE.erl @@ -33,7 +33,8 @@ dirty_nif_exception/1, call_dirty_nif_exception/1, dirty_scheduler_exit/1, dirty_call_while_terminated/1, dirty_heap_access/1, dirty_process_info/1, - dirty_process_register/1, dirty_process_trace/1]). + dirty_process_register/1, dirty_process_trace/1, + code_purge/1]). -define(nif_stub,nif_stub_error(?LINE)). @@ -48,7 +49,8 @@ all() -> dirty_heap_access, dirty_process_info, dirty_process_register, - dirty_process_trace]. + dirty_process_trace, + code_purge]. init_per_suite(Config) -> try erlang:system_info(dirty_cpu_schedulers) of @@ -349,6 +351,75 @@ dirty_process_trace(Config) when is_list(Config) -> ok end). +dirty_code_test_code() -> + " +-module(dirty_code_test). + +-export([func/1]). + +func(Fun) -> + Fun(), + blipp:blapp(). + +". + +code_purge(Config) when is_list(Config) -> + Path = ?config(data_dir, Config), + File = filename:join(Path, "dirty_code_test.erl"), + ok = file:write_file(File, dirty_code_test_code()), + {ok, dirty_code_test, Bin} = compile:file(File, [binary]), + {module, dirty_code_test} = erlang:load_module(dirty_code_test, Bin), + Start = erlang:monotonic_time(), + {Pid1, Mon1} = spawn_monitor(fun () -> + dirty_code_test:func(fun () -> + %% Sleep for 6 seconds + %% in dirty nif... + dirty_sleeper() + end) + end), + {module, dirty_code_test} = erlang:load_module(dirty_code_test, Bin), + {Pid2, Mon2} = spawn_monitor(fun () -> + dirty_code_test:func(fun () -> + %% Sleep for 6 seconds + %% in dirty nif... + dirty_sleeper() + end) + end), + receive + {'DOWN', Mon1, process, Pid1, _} -> + ct:fail(premature_death) + after 100 -> + ok + end, + true = erlang:purge_module(dirty_code_test), + receive + {'DOWN', Mon1, process, Pid1, Reason} -> + killed = Reason + end, + receive + {'DOWN', Mon2, process, Pid2, _} -> + ct:fail(premature_death) + after 100 -> + ok + end, + true = erlang:delete_module(dirty_code_test), + receive + {'DOWN', Mon2, process, Pid2, _} -> + ct:fail(premature_death) + after 100 -> + ok + end, + true = erlang:purge_module(dirty_code_test), + receive + {'DOWN', Mon2, process, Pid2, Reason} -> + killed = Reason + end, + End = erlang:monotonic_time(), + Time = erlang:convert_time_unit(End-Start, native, milli_seconds), + io:format("Time=~p~n", [Time]), + true = Time =< 1000, + ok. + %% %% Internal... %% -- cgit v1.2.3 From c429c3d042ba274d4225a6d79b2f1df8cfd19983 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Thu, 25 Aug 2016 15:34:43 +0200 Subject: Fix tracing of processes executing dirty --- erts/emulator/test/dirty_nif_SUITE.erl | 42 ++++++++++++++++++---- .../test/dirty_nif_SUITE_data/dirty_nif_SUITE.c | 27 ++++++++++++++ 2 files changed, 63 insertions(+), 6 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/dirty_nif_SUITE.erl b/erts/emulator/test/dirty_nif_SUITE.erl index c2d2e58957..653b96557e 100644 --- a/erts/emulator/test/dirty_nif_SUITE.erl +++ b/erts/emulator/test/dirty_nif_SUITE.erl @@ -34,7 +34,7 @@ dirty_scheduler_exit/1, dirty_call_while_terminated/1, dirty_heap_access/1, dirty_process_info/1, dirty_process_register/1, dirty_process_trace/1, - code_purge/1]). + code_purge/1, dirty_nif_send_traced/1]). -define(nif_stub,nif_stub_error(?LINE)). @@ -50,7 +50,8 @@ all() -> dirty_process_info, dirty_process_register, dirty_process_trace, - code_purge]. + code_purge, + dirty_nif_send_traced]. init_per_suite(Config) -> try erlang:system_info(dirty_cpu_schedulers) of @@ -393,8 +394,8 @@ code_purge(Config) when is_list(Config) -> end, true = erlang:purge_module(dirty_code_test), receive - {'DOWN', Mon1, process, Pid1, Reason} -> - killed = Reason + {'DOWN', Mon1, process, Pid1, Reason1} -> + killed = Reason1 end, receive {'DOWN', Mon2, process, Pid2, _} -> @@ -411,8 +412,8 @@ code_purge(Config) when is_list(Config) -> end, true = erlang:purge_module(dirty_code_test), receive - {'DOWN', Mon2, process, Pid2, Reason} -> - killed = Reason + {'DOWN', Mon2, process, Pid2, Reason2} -> + killed = Reason2 end, End = erlang:monotonic_time(), Time = erlang:convert_time_unit(End-Start, native, milli_seconds), @@ -420,6 +421,34 @@ code_purge(Config) when is_list(Config) -> true = Time =< 1000, ok. +dirty_nif_send_traced(Config) when is_list(Config) -> + Parent = self(), + Rcvr = spawn_link(fun() -> + Self = self(), + receive {ok, Self} -> ok end, + Parent ! {Self, received} + end), + Sndr = spawn_link(fun () -> + receive {Parent, go} -> ok end, + {ok, Rcvr} = send_wait_from_dirty_nif(Rcvr), + Parent ! {self(), sent} + end), + 1 = erlang:trace(Sndr, true, [send]), + Start = erlang:monotonic_time(), + Sndr ! {self(), go}, + receive {trace, Sndr, send, {ok, Rcvr}, Rcvr} -> ok end, + receive {Rcvr, received} -> ok end, + End1 = erlang:monotonic_time(), + Time1 = erlang:convert_time_unit(End1-Start, native, 1000), + io:format("Time1: ~p milliseconds~n", [Time1]), + true = Time1 < 500, + receive {Sndr, sent} -> ok end, + End2 = erlang:monotonic_time(), + Time2 = erlang:convert_time_unit(End2-Start, native, 1000), + io:format("Time2: ~p milliseconds~n", [Time2]), + true = Time2 >= 1900, + ok. + %% %% Internal... %% @@ -502,6 +531,7 @@ mcall(Node, Funs) -> lib_loaded() -> false. call_dirty_nif(_,_,_) -> ?nif_stub. send_from_dirty_nif(_) -> ?nif_stub. +send_wait_from_dirty_nif(_) -> ?nif_stub. call_dirty_nif_exception(_) -> ?nif_stub. call_dirty_nif_zero_args() -> ?nif_stub. dirty_call_while_terminated_nif(_) -> ?nif_stub. diff --git a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c index d92933a096..a0019e5d95 100644 --- a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c +++ b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c @@ -100,6 +100,32 @@ static ERL_NIF_TERM send_from_dirty_nif(ErlNifEnv* env, int argc, const ERL_NIF_ return result; } +static ERL_NIF_TERM send_wait_from_dirty_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ERL_NIF_TERM result; + ErlNifPid pid; + ErlNifEnv* menv; + int res; + + if (!enif_get_local_pid(env, argv[0], &pid)) + return enif_make_badarg(env); + result = enif_make_tuple2(env, enif_make_atom(env, "ok"), enif_make_pid(env, &pid)); + menv = enif_alloc_env(); + res = enif_send(env, &pid, menv, result); + enif_free_env(menv); + +#ifdef __WIN32__ + Sleep(2000); +#else + sleep(2); +#endif + + if (!res) + return enif_make_badarg(env); + else + return result; +} + static ERL_NIF_TERM call_dirty_nif_exception(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { switch (argc) { @@ -237,6 +263,7 @@ static ErlNifFunc nif_funcs[] = {"lib_loaded", 0, lib_loaded}, {"call_dirty_nif", 3, call_dirty_nif}, {"send_from_dirty_nif", 1, send_from_dirty_nif, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"send_wait_from_dirty_nif", 1, send_wait_from_dirty_nif, ERL_NIF_DIRTY_JOB_IO_BOUND}, {"call_dirty_nif_exception", 1, call_dirty_nif_exception, ERL_NIF_DIRTY_JOB_IO_BOUND}, {"call_dirty_nif_zero_args", 0, call_dirty_nif_zero_args, ERL_NIF_DIRTY_JOB_CPU_BOUND}, {"dirty_sleeper", 0, dirty_sleeper, ERL_NIF_DIRTY_JOB_IO_BOUND}, -- cgit v1.2.3 From e643c301c1402fb58ccc52f729c6b0b16c5c12e7 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Mon, 25 Jul 2016 19:39:33 +0200 Subject: Adjust process_SUITE:no_priority_inversion2 --- erts/emulator/test/process_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index dae8990f56..7462c8c593 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -2376,7 +2376,7 @@ no_priority_inversion2(Config) when is_list(Config) -> [{priority, max}, monitor, link]) end, lists:seq(1, 2*erlang:system_info(schedulers))), - receive after 500 -> ok end, + receive after 2000 -> ok end, {PL, ML} = spawn_opt(fun () -> tok_loop() end, -- cgit v1.2.3 From 93fb8ecb7ed41e7c441b1c72901d6db76c24fd8d Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Tue, 26 Jul 2016 18:22:18 +0200 Subject: Fix dirty_nif_SUITE:dirty_call_while_terminated test case Prevent binary from being prematurely GCed --- erts/emulator/test/dirty_nif_SUITE.erl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/dirty_nif_SUITE.erl b/erts/emulator/test/dirty_nif_SUITE.erl index 83b098a704..1a6737d59a 100644 --- a/erts/emulator/test/dirty_nif_SUITE.erl +++ b/erts/emulator/test/dirty_nif_SUITE.erl @@ -230,7 +230,11 @@ dirty_call_while_terminated(Config) when is_list(Config) -> process_info(self(), binary))), process_flag(trap_exit, OT), - ok. + try + blipp:blupp(Bin) + catch + _ : _ -> ok + end. dirty_heap_access(Config) when is_list(Config) -> {ok, Node} = start_node(Config), -- cgit v1.2.3 From 1b4a59c405e6bd3532921d5c534e2264bb05b2eb Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Mon, 29 Aug 2016 19:21:53 +0200 Subject: Remove old purge strategy --- erts/emulator/test/code_SUITE.erl | 168 +------------------------------------- 1 file changed, 3 insertions(+), 165 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index 34515efa3d..82607424b5 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -22,8 +22,7 @@ -export([all/0, suite/0, init_per_suite/1, end_per_suite/1, versions/1,new_binary_types/1, call_purged_fun_code_gone/1, call_purged_fun_code_reload/1, call_purged_fun_code_there/1, - t_check_process_code/1,t_check_old_code/1, - t_check_process_code_ets/1, + t_check_old_code/1, external_fun/1,get_chunk/1,module_md5/1,make_stub/1, make_stub_many_funs/1,constant_pools/1,constant_refc_binaries/1, false_dependency/1,coverage/1,fun_confusion/1, @@ -36,8 +35,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [versions, new_binary_types, call_purged_fun_code_gone, - call_purged_fun_code_reload, call_purged_fun_code_there, t_check_process_code, - t_check_process_code_ets, t_check_old_code, external_fun, get_chunk, + call_purged_fun_code_reload, call_purged_fun_code_there, + t_check_old_code, external_fun, get_chunk, module_md5, make_stub, make_stub_many_funs, constant_pools, constant_refc_binaries, false_dependency, coverage, fun_confusion, t_copy_literals, t_copy_literals_frags]. @@ -276,98 +275,6 @@ call_purged_fun_test(Priv, Data, Type) -> end, ok. -t_check_process_code(Config) when is_list(Config) -> - case check_process_code_handle(indirect_references) of - false -> {skipped, "check_process_code() ignores funs"}; - true -> t_check_process_code_test(Config) - end. - -t_check_process_code_test(Config) -> - Priv = proplists:get_value(priv_dir, Config), - Data = proplists:get_value(data_dir, Config), - File = filename:join(Data, "my_code_test"), - Code = filename:join(Priv, "my_code_test"), - - catch erlang:purge_module(my_code_test), - catch erlang:delete_module(my_code_test), - catch erlang:purge_module(my_code_test), - - {ok,my_code_test} = c:c(File, [{outdir,Priv}]), - - MyFun = fun(X, Y) -> X + Y end, %Confuse things. - F = my_code_test:make_fun(42), - 2 = fun_refc(F), - MyFun2 = fun(X, Y) -> X * Y end, %Confuse things. - 44 = F(2), - - %% Delete the module and call the fun again. - true = erlang:delete_module(my_code_test), - 2 = fun_refc(F), - 45 = F(3), - {'EXIT',{undef,_}} = (catch my_code_test:make_fun(33)), - - %% The fun should still be there, preventing purge. - true = erlang:check_process_code(self(), my_code_test), - gc(), - gc(), %Place funs on the old heap. - true = erlang:check_process_code(self(), my_code_test), - - %% Using the funs here guarantees that they will not be prematurely garbed. - 48 = F(6), - 3 = MyFun(1, 2), - 12 = MyFun2(3, 4), - - %% Kill all funs. - t_check_process_code1(Code, []). - -%% The real fun was killed, but we have some fakes which look similar. - -t_check_process_code1(Code, Fakes) -> - MyFun = fun(X, Y) -> X + Y + 1 end, %Confuse things. - false = erlang:check_process_code(self(), my_code_test), - 4 = MyFun(1, 2), - t_check_process_code2(Code, Fakes). - -t_check_process_code2(Code, _) -> - false = erlang:check_process_code(self(), my_code_test), - true = erlang:purge_module(my_code_test), - - %% In the next test we will load the same module twice. - {module,my_code_test} = code:load_abs(Code), - F = my_code_test:make_fun(37), - 2 = fun_refc(F), - false = erlang:check_process_code(self(), my_code_test), - {module,my_code_test} = code:load_abs(Code), - 2 = fun_refc(F), - - %% Still false because the fun with the same identify is found - %% in the current code. - false = erlang:check_process_code(self(), my_code_test), - - %% Some fake funs in the same module should not do any difference. - false = erlang:check_process_code(self(), my_code_test), - - 38 = F(1), - t_check_process_code3(Code, F, []). - -t_check_process_code3(Code, F, Fakes) -> - Pid = spawn_link(fun() -> body(F, Fakes) end), - true = erlang:purge_module(my_code_test), - false = erlang:check_process_code(self(), my_code_test), - false = erlang:check_process_code(Pid, my_code_test), - - true = erlang:delete_module(my_code_test), - true = erlang:check_process_code(self(), my_code_test), - true = erlang:check_process_code(Pid, my_code_test), - 39 = F(2), - t_check_process_code4(Code, Pid). - -t_check_process_code4(_Code, Pid) -> - Pid ! drop_funs, - receive after 1 -> ok end, - false = erlang:check_process_code(Pid, my_code_test), - ok. - body(F, Fakes) -> receive jog -> @@ -388,72 +295,6 @@ gc() -> gc1(). gc1() -> ok. -%% Test check_process_code/2 in combination with a fun obtained from an ets table. -t_check_process_code_ets(Config) when is_list(Config) -> - case check_process_code_handle(indirect_references) of - false -> - {skipped, "check_process_code() ignores funs"}; - true -> - case test_server:is_native(?MODULE) of - true -> - {skip,"Native code"}; - false -> - do_check_process_code_ets(Config) - end - end. - -do_check_process_code_ets(Config) -> - Priv = proplists:get_value(priv_dir, Config), - Data = proplists:get_value(data_dir, Config), - File = filename:join(Data, "my_code_test"), - - catch erlang:purge_module(my_code_test), - catch erlang:delete_module(my_code_test), - catch erlang:purge_module(my_code_test), - {ok,my_code_test} = c:c(File, [{outdir,Priv}]), - - T = ets:new(my_code_test, []), - ets:insert(T, {7,my_code_test:make_fun(107)}), - ets:insert(T, {8,my_code_test:make_fun(108)}), - erlang:delete_module(my_code_test), - false = erlang:check_process_code(self(), my_code_test), - Body = fun() -> - [{7,F1}] = ets:lookup(T, 7), - [{8,F2}] = ets:lookup(T, 8), - IdleLoop = fun() -> receive _X -> ok end end, - RecLoop = fun(Again) -> - receive - call -> 110 = F1(3), - 100 = F2(-8), - Again(Again); - {drop_funs,To} -> - To ! funs_dropped, - IdleLoop() - end - end, - true = erlang:check_process_code(self(), my_code_test), - RecLoop(RecLoop) - end, - Pid = spawn_link(Body), - receive after 1 -> ok end, - true = erlang:check_process_code(Pid, my_code_test), - Pid ! call, - Pid ! {drop_funs,self()}, - - receive - funs_dropped -> ok; - Other -> ct:fail({unexpected,Other}) - after 10000 -> - ct:fail(no_funs_dropped_answer) - end, - - false = erlang:check_process_code(Pid, my_code_test), - ok. - -fun_refc(F) -> - {refc,Count} = erlang:fun_info(F, refc), - Count. - %% Test the erlang:check_old_code/1 BIF. t_check_old_code(Config) when is_list(Config) -> @@ -1137,9 +978,6 @@ flush() -> id(I) -> I. -check_process_code_handle(What) -> - lists:member(What, erlang:system_info(check_process_code)). - wait_until(Fun) -> case Fun() of true -> -- cgit v1.2.3 From 7be8e2309d87dbb6e922cb0ca56f031f9e4ec12b Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Tue, 30 Aug 2016 12:16:57 +0200 Subject: Avoid selective receive in code-purger process The code purger process handles vast amounts of messages when there are lots of processes alive. A single message in the message queue that does not match will in such cases cause lots of extra work. The code purger process now always picks the first message in the message queue, and by this avoid this extra work. --- erts/emulator/test/code_SUITE.erl | 62 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index 82607424b5..8427bb134d 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -22,7 +22,7 @@ -export([all/0, suite/0, init_per_suite/1, end_per_suite/1, versions/1,new_binary_types/1, call_purged_fun_code_gone/1, call_purged_fun_code_reload/1, call_purged_fun_code_there/1, - t_check_old_code/1, + multi_proc_purge/1, t_check_old_code/1, external_fun/1,get_chunk/1,module_md5/1,make_stub/1, make_stub_many_funs/1,constant_pools/1,constant_refc_binaries/1, false_dependency/1,coverage/1,fun_confusion/1, @@ -36,7 +36,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [versions, new_binary_types, call_purged_fun_code_gone, call_purged_fun_code_reload, call_purged_fun_code_there, - t_check_old_code, external_fun, get_chunk, + multi_proc_purge, t_check_old_code, external_fun, get_chunk, module_md5, make_stub, make_stub_many_funs, constant_pools, constant_refc_binaries, false_dependency, coverage, fun_confusion, t_copy_literals, t_copy_literals_frags]. @@ -275,6 +275,64 @@ call_purged_fun_test(Priv, Data, Type) -> end, ok. +multi_proc_purge(Config) when is_list(Config) -> + %% + %% Make sure purge requests aren't lost when + %% purger process is working. + %% + Priv = proplists:get_value(priv_dir, Config), + Data = proplists:get_value(data_dir, Config), + File1 = filename:join(Data, "my_code_test"), + File2 = filename:join(Data, "my_code_test2"), + + {ok,my_code_test} = c:c(File1, [{outdir,Priv}]), + {ok,my_code_test2} = c:c(File2, [{outdir,Priv}]), + erlang:delete_module(my_code_test), + erlang:delete_module(my_code_test2), + + Self = self(), + + Fun1 = fun () -> + erts_code_purger:purge(my_code_test), + Self ! {self(), done} + end, + Fun2 = fun () -> + erts_code_purger:soft_purge(my_code_test2), + Self ! {self(), done} + end, + Fun3 = fun () -> + erts_code_purger:purge('__nonexisting_module__'), + Self ! {self(), done} + end, + Fun4 = fun () -> + erts_code_purger:soft_purge('__another_nonexisting_module__'), + Self ! {self(), done} + end, + + Pid1 = spawn_link(Fun1), + Pid2 = spawn_link(Fun2), + Pid3 = spawn_link(Fun3), + Pid4 = spawn_link(Fun4), + Pid5 = spawn_link(Fun1), + Pid6 = spawn_link(Fun2), + Pid7 = spawn_link(Fun3), + receive after 50 -> ok end, + Pid8 = spawn_link(Fun4), + Pid9 = spawn_link(Fun1), + Pid10 = spawn_link(Fun2), + Pid11 = spawn_link(Fun3), + Pid12 = spawn_link(Fun4), + Pid13 = spawn_link(Fun1), + receive after 50 -> ok end, + Pid14 = spawn_link(Fun2), + Pid15 = spawn_link(Fun3), + Pid16 = spawn_link(Fun4), + + lists:foreach(fun (P) -> receive {P, done} -> ok end end, + [Pid1, Pid2, Pid3, Pid4, Pid5, Pid6, Pid7, Pid8, + Pid9, Pid10, Pid11, Pid12, Pid13, Pid14, Pid15, Pid16]), + ok. + body(F, Fakes) -> receive jog -> -- cgit v1.2.3 From ae3e177c514c35483184b0cb52c00b4452ca72ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 16 Aug 2016 08:27:39 +0200 Subject: compiler: Eliminate use of sys_pre_expand sys_pre_expand previously did a lot more work, for example, translating records and funs, but now is merely a grab bag of small transformations. Move those transformations to v3_core. --- erts/emulator/test/match_spec_SUITE.erl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/match_spec_SUITE.erl b/erts/emulator/test/match_spec_SUITE.erl index 6733237b20..34e956bc21 100644 --- a/erts/emulator/test/match_spec_SUITE.erl +++ b/erts/emulator/test/match_spec_SUITE.erl @@ -427,13 +427,13 @@ silent_no_ms(Config) when is_list(Config) -> %% [{trace,Tracee,call,{?MODULE,f1,[start]}}, {trace,Tracee,return_to, - {?MODULE,'-silent_no_ms/1-fun-2-',0}}, + {?MODULE,'-silent_no_ms/1-fun-3-',0}}, {trace,Tracee,call,{?MODULE,f2,[f,g]}}, {trace,Tracee,return_to, - {?MODULE,'-silent_no_ms/1-fun-2-',0}}, + {?MODULE,'-silent_no_ms/1-fun-3-',0}}, {trace,Tracee,call,{erlang,integer_to_list,[2]}}, {trace,Tracee,return_to, - {?MODULE,'-silent_no_ms/1-fun-2-',0}}, + {?MODULE,'-silent_no_ms/1-fun-3-',0}}, {trace,Tracee,call,{?MODULE,f2,[h,i]}}, {trace,Tracee,return_to,{?MODULE,f3,2}}] end). @@ -484,7 +484,7 @@ ms_trace2(Config) when is_list(Config) -> %% %% Expected: (no return_to for global call trace) %% - Origin = {match_spec_SUITE,'-ms_trace2/1-fun-0-',1}, + Origin = {match_spec_SUITE,'-ms_trace2/1-fun-1-',1}, [{trace_ts,Tracee,call, {?MODULE,fn, [[all],[call,return_to,{tracer,Tracer}]]}, @@ -574,7 +574,7 @@ ms_trace3(Config) when is_list(Config) -> %% %% Expected: (no return_to for global call trace) %% - Origin = {match_spec_SUITE,'-ms_trace3/1-fun-1-',2}, + Origin = {match_spec_SUITE,'-ms_trace3/1-fun-2-',2}, [{trace_ts,Controller,call, {?MODULE,fn,[TraceeName,[all], [call,return_to,send,'receive', -- cgit v1.2.3 From bc9d81f0e4b62927cf97e3e5b31fdb88ab3bceb9 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Fri, 2 Sep 2016 10:43:39 +0200 Subject: Ensure long enough sleep in driver_SUITE:timer_delay driver --- erts/emulator/test/driver_SUITE.erl | 6 +--- erts/emulator/test/driver_SUITE_data/timer_drv.c | 44 ++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 8 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl index 1df72193a6..2fbf6eae61 100644 --- a/erts/emulator/test/driver_SUITE.erl +++ b/erts/emulator/test/driver_SUITE.erl @@ -452,11 +452,7 @@ timer_delay(Config) when is_list(Config) -> TimeBefore = erlang:monotonic_time(), Timeout0 = 350, erlang:port_command(Port, <>), - Timeout = Timeout0 + - case os:type() of - {win32,_} -> 0; %Driver doesn't sleep on Windows. - _ -> 1000 - end, + Timeout = Timeout0 + 1000, receive {Port,{data,[?TIMER]}} -> Elapsed = erl_millisecs() - erl_millisecs(TimeBefore), diff --git a/erts/emulator/test/driver_SUITE_data/timer_drv.c b/erts/emulator/test/driver_SUITE_data/timer_drv.c index 57538e0d57..c3ce3b6e49 100644 --- a/erts/emulator/test/driver_SUITE_data/timer_drv.c +++ b/erts/emulator/test/driver_SUITE_data/timer_drv.c @@ -1,5 +1,13 @@ #include #include "erl_driver.h" +#ifdef __WIN32__ +# include +#else +# include +# include +# include +# include +#endif #define get_int32(s) ((((unsigned char*) (s))[0] << 24) | \ (((unsigned char*) (s))[1] << 16) | \ @@ -17,6 +25,7 @@ static ErlDrvData timer_start(ErlDrvPort, char*); static void timer_stop(ErlDrvData); static void timer_read(ErlDrvData, char*, ErlDrvSizeT); static void timer(ErlDrvData); +static void ms_sleep(int ms); static ErlDrvEntry timer_driver_entry = { @@ -75,9 +84,7 @@ static void timer_read(ErlDrvData p, char *buf, ErlDrvSizeT len) reply[0] = CANCELLED; driver_output(port, reply, 1); } else if (buf[0] == DELAY_START_TIMER) { -#ifndef __WIN32__ - sleep(1); -#endif + ms_sleep(1000); driver_set_timer(port, get_int32(buf + 1)); } } @@ -95,3 +102,34 @@ static void timer(ErlDrvData port) reply[0] = TIMER; driver_output((ErlDrvPort)port, reply, 1); } + +static void +ms_sleep(int ms) +{ + /* Important that we do not return too early... */ + ErlDrvTime time, timeout_time; + + time = erl_drv_monotonic_time(ERL_DRV_USEC); + + timeout_time = time + ((ErlDrvTime) ms)*1000; + + while (time < timeout_time) { + ErlDrvTime timeout = timeout_time - time; + +#ifdef __WIN32__ + Sleep((DWORD) (timeout / 1000)); +#else + { + struct timeval tv; + + tv.tv_sec = (long) timeout / (1000*1000); + tv.tv_usec = (long) timeout % (1000*1000); + + select(0, NULL, NULL, NULL, &tv); + } +#endif + + time = erl_drv_monotonic_time(ERL_DRV_USEC); + } + +} -- cgit v1.2.3 From 18c52187b1714284416a8a1d618ce4db831d1a45 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Fri, 2 Sep 2016 15:05:26 +0200 Subject: Introduce literal sweep of native stack in new purge strategy --- erts/emulator/test/hipe_SUITE.erl | 3 +++ 1 file changed, 3 insertions(+) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/hipe_SUITE.erl b/erts/emulator/test/hipe_SUITE.erl index 3e682b8d88..a556b4ddc0 100644 --- a/erts/emulator/test/hipe_SUITE.erl +++ b/erts/emulator/test/hipe_SUITE.erl @@ -51,6 +51,9 @@ t_copy_literals(Config) when is_list(Config) -> true = erlang:delete_module(literals), true = erlang:purge_module(literals), + %% Give the literal collector some time to work... + receive after 2000 -> ok end, + %% check that the ex-literals are ok [a,b,c] = ref_cell:call(PA, get), {a,b,c} = ref_cell:call(PB, get), -- cgit v1.2.3 From 986d32a62b20c32338dac4dfd27c141c8f9be0fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 20 Jun 2016 13:25:04 +0200 Subject: Implement the new ceil/1 and floor/1 guard BIFs Implement as ceil/1 and floor/1 as new guard BIFs (essentially part of Erlang language). They are guard BIFs because trunc/1 is a guard BIF. It would be strange to have trunc/1 as a part of the language, but not ceil/1 and floor/1. --- erts/emulator/test/num_bif_SUITE.erl | 84 ++++++++++++++++++++++++++++-------- 1 file changed, 67 insertions(+), 17 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/num_bif_SUITE.erl b/erts/emulator/test/num_bif_SUITE.erl index d1c9648017..1a1ab0e5e0 100644 --- a/erts/emulator/test/num_bif_SUITE.erl +++ b/erts/emulator/test/num_bif_SUITE.erl @@ -32,6 +32,8 @@ %% list_to_integer/1 %% round/1 %% trunc/1 +%% floor/1 +%% ceil/1 %% integer_to_binary/1 %% integer_to_binary/2 %% binary_to_integer/1 @@ -41,7 +43,7 @@ t_float_to_string/1, t_integer_to_string/1, t_string_to_integer/1, t_list_to_integer_edge_cases/1, t_string_to_float_safe/1, t_string_to_float_risky/1, - t_round/1, t_trunc/1 + t_round/1, t_trunc_and_friends/1 ]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -49,7 +51,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [t_abs, t_float, t_float_to_string, t_integer_to_string, {group, t_string_to_float}, t_string_to_integer, t_round, - t_trunc, t_list_to_integer_edge_cases]. + t_trunc_and_friends, t_list_to_integer_edge_cases]. groups() -> [{t_string_to_float, [], @@ -295,30 +297,78 @@ t_round(Config) when is_list(Config) -> -4294967297 = -round(id(4294967296.9)), ok. -t_trunc(Config) when is_list(Config) -> - 0 = trunc(id(0.0)), - 5 = trunc(id(5.3333)), - -10 = trunc(id(-10.978987)), +%% Test trunc/1, floor/1, ceil/1, and round/1. +t_trunc_and_friends(_Config) -> + MinusZero = 0.0 / (-1.0), + 0 = trunc_and_friends(MinusZero), + 0 = trunc_and_friends(0.0), + 5 = trunc_and_friends(5.3333), + -10 = trunc_and_friends(-10.978987), - % The largest smallnum, converted to float (OTP-3722): + %% The largest smallnum, converted to float (OTP-3722): X = id((1 bsl 27) - 1), - F = id(X + 0.0), + F = X + 0.0, io:format("X = ~p/~w/~w, F = ~p/~w/~w, trunc(F) = ~p/~w/~w~n", [X, X, binary_to_list(term_to_binary(X)), F, F, binary_to_list(term_to_binary(F)), - trunc(F), trunc(F), binary_to_list(term_to_binary(trunc(F)))]), - X = trunc(F), - X = trunc(F+1)-1, - X = trunc(F-1)+1, - X = -trunc(-F), - X = -trunc(-F-1)-1, - X = -trunc(-F+1)+1, + trunc_and_friends(F), + trunc_and_friends(F), + binary_to_list(term_to_binary(trunc_and_friends(F)))]), + X = trunc_and_friends(F), + X = trunc_and_friends(F+1)-1, + X = trunc_and_friends(F-1)+1, + X = -trunc_and_friends(-F), + X = -trunc_and_friends(-F-1)-1, + X = -trunc_and_friends(-F+1)+1, %% Bignums. - 4294967305 = trunc(id(4294967305.7)), - -4294967305 = trunc(id(-4294967305.7)), + 4294967305 = trunc_and_friends(4294967305.7), + -4294967305 = trunc_and_friends(-4294967305.7), + 18446744073709551616 = trunc_and_friends(float(1 bsl 64)), + -18446744073709551616 = trunc_and_friends(-float(1 bsl 64)), + + %% Random. + t_trunc_and_friends_rand(100), ok. +t_trunc_and_friends_rand(0) -> + ok; +t_trunc_and_friends_rand(N) -> + F0 = rand:uniform() * math:pow(10, 50*rand:normal()), + F = case rand:uniform() of + U when U < 0.5 -> -F0; + _ -> F0 + end, + _ = trunc_and_friends(F), + t_trunc_and_friends_rand(N-1). + +trunc_and_friends(F) -> + Trunc = trunc(F), + Floor = floor(F), + Ceil = ceil(F), + Round = round(F), + + Trunc = trunc(Trunc), + Floor = floor(Floor), + Ceil = ceil(Ceil), + Round = round(Round), + + Trunc = trunc(float(Trunc)), + Floor = floor(float(Floor)), + Ceil = ceil(float(Ceil)), + Round = round(float(Round)), + + true = Floor =< Trunc andalso Trunc =< Ceil, + true = Ceil - Floor =< 1, + true = Round =:= Floor orelse Round =:= Ceil, + + if + F < 0 -> + Trunc = Ceil; + true -> + Trunc = Floor + end, + Trunc. %% Tests integer_to_binary/1. -- cgit v1.2.3 From 2a65c850ff50ea5ae0f0e4a239bcb88781dedaf8 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Mon, 22 Aug 2016 15:22:06 +0200 Subject: Fix process_SUITE system_task_blast and no_priority_inversion2 --- erts/emulator/test/process_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index dae8990f56..cf43369974 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -2428,7 +2428,7 @@ no_priority_inversion2(Config) when is_list(Config) -> request_gc(Pid, Prio) -> Ref = make_ref(), - erts_internal:request_system_task(Pid, Prio, {garbage_collect, Ref}), + erts_internal:request_system_task(Pid, Prio, {garbage_collect, Ref, major}), Ref. system_task_blast(Config) when is_list(Config) -> -- cgit v1.2.3 From 314cbf6d2d4fb356dad6f985f76b220052a97f28 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 6 Sep 2016 17:40:02 +0200 Subject: erts: Improve nif_SUITE:upgrade test to include upgrade from deleted (old) module instance --- erts/emulator/test/nif_SUITE.erl | 53 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 8df2733fac..b5adf2ef7a 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -174,11 +174,33 @@ upgrade(Config) when is_list(Config) -> true = erlang:delete_module(nif_mod), [] = nif_mod_call_history(), + %% Repeat upgrade again but from old (deleted) instance + {module,nif_mod} = erlang:load_module(nif_mod,Bin), + undefined = nif_mod:lib_version(), + 1 = call(Pid,lib_version), + [{lib_version,1,9,109}] = nif_mod_call_history(), + + ok = nif_mod:load_nif_lib(Config, 1), + 1 = nif_mod:lib_version(), + [{upgrade,1,10,110},{lib_version,1,11,111}] = nif_mod_call_history(), + + upgraded = call(Pid,upgrade), + false = check_process_code(Pid, nif_mod), + true = erlang:purge_module(nif_mod), + [{unload,1,12,112}] = nif_mod_call_history(), + + 1 = nif_mod:lib_version(), + [{lib_version,1,13,113}] = nif_mod_call_history(), + + true = erlang:delete_module(nif_mod), + [] = nif_mod_call_history(), + + Pid ! die, {'DOWN', MRef, process, Pid, normal} = receive_any(), false = check_process_code(Pid, nif_mod), true = erlang:purge_module(nif_mod), - [{unload,1,9,109}] = nif_mod_call_history(), + [{unload,1,14,114}] = nif_mod_call_history(), %% Module upgrade with different lib version {module,nif_mod} = erlang:load_module(nif_mod,Bin), @@ -215,11 +237,38 @@ upgrade(Config) when is_list(Config) -> true = erlang:delete_module(nif_mod), [] = nif_mod_call_history(), + + %% Reverse upgrade but from old (deleted) instance + {module,nif_mod} = erlang:load_module(nif_mod,Bin), + undefined = nif_mod:lib_version(), + [] = nif_mod_call_history(), + 2 = call(Pid2,lib_version), + [{lib_version,2,4,204}] = nif_mod_call_history(), + + ok = nif_mod:load_nif_lib(Config, 1), + 1 = nif_mod:lib_version(), + [{upgrade,1,1,101},{lib_version,1,2,102}] = nif_mod_call_history(), + + 2 = call(Pid2,lib_version), + [{lib_version,2,5,205}] = nif_mod_call_history(), + + upgraded = call(Pid2,upgrade), + false = check_process_code(Pid2, nif_mod), + true = erlang:purge_module(nif_mod), + [{unload,2,6,206}] = nif_mod_call_history(), + + 1 = nif_mod:lib_version(), + [{lib_version,1,3,103}] = nif_mod_call_history(), + + true = erlang:delete_module(nif_mod), + [] = nif_mod_call_history(), + + Pid2 ! die, {'DOWN', MRef2, process, Pid2, normal} = receive_any(), false= check_process_code(Pid2, nif_mod), true = erlang:purge_module(nif_mod), - [{unload,2,4,204}] = nif_mod_call_history(), + [{unload,1,4,104}] = nif_mod_call_history(), true = lists:member(?MODULE, erlang:system_info(taints)), true = lists:member(nif_mod, erlang:system_info(taints)), -- cgit v1.2.3 From 359e05121dab023585715b0e42506afd94f2e1f1 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 7 Sep 2016 17:11:03 +0200 Subject: erts: Add nif_SUITE:t_on_load --- erts/emulator/test/nif_SUITE.erl | 137 ++++++++++++++++++++++++++ erts/emulator/test/nif_SUITE_data/nif_mod.erl | 10 ++ 2 files changed, 147 insertions(+) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index b5adf2ef7a..9c1694fa8a 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -29,6 +29,7 @@ -export([all/0, suite/0, init_per_testcase/2, end_per_testcase/2, basic/1, reload/1, upgrade/1, heap_frag/1, + t_on_load/1, types/1, many_args/1, binaries/1, get_string/1, get_atom/1, maps/1, api_macros/1, @@ -68,6 +69,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [basic, reload, upgrade, heap_frag, types, many_args, + t_on_load, binaries, get_string, get_atom, maps, api_macros, from_array, iolist_as_binary, resource, resource_binary, resource_takeover, threading, send, send2, send3, @@ -83,10 +85,19 @@ all() -> nif_port_command, nif_snprintf]. +init_per_testcase(t_on_load, Config) -> + ets:new(nif_SUITE, [named_table]), + Config; init_per_testcase(_Case, Config) -> Config. +end_per_testcase(t_on_load, _Config) -> + ets:delete(nif_SUITE), + testcase_cleanup(); end_per_testcase(_Func, _Config) -> + testcase_cleanup(). + +testcase_cleanup() -> P1 = code:purge(nif_mod), Del = code:delete(nif_mod), P2 = code:purge(nif_mod), @@ -275,6 +286,132 @@ upgrade(Config) when is_list(Config) -> verify_tmpmem(TmpMem), ok. +%% Test loading/upgrade in on_load +t_on_load(Config) when is_list(Config) -> + TmpMem = tmpmem(), + ensure_lib_loaded(Config), + + Data = proplists:get_value(data_dir, Config), + File = filename:join(Data, "nif_mod"), + {ok,nif_mod,Bin} = compile:file(File, [binary,return_errors, + {d,'USE_ON_LOAD'}]), + + %% Use ETS to tell nif_mod:on_load what to do + ets:insert(nif_SUITE, {data_dir, Data}), + ets:insert(nif_SUITE, {lib_version, 1}), + {module,nif_mod} = code:load_binary(nif_mod,File,Bin), + hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()), + [{load,1,1,101},{get_priv_data_ptr,1,2,102}] = nif_mod_call_history(), + + {Pid,MRef} = nif_mod:start(), + 1 = call(Pid,lib_version), + [{lib_version,1,3,103}] = nif_mod_call_history(), + + %% Module upgrade with same lib-version + {module,nif_mod} = code:load_binary(nif_mod,File,Bin), + 1 = nif_mod:lib_version(), + 1 = call(Pid,lib_version), + [{upgrade,1,4,104},{lib_version,1,5,105},{lib_version,1,6,106}] = nif_mod_call_history(), + + upgraded = call(Pid,upgrade), + false = check_process_code(Pid, nif_mod), + true = code:soft_purge(nif_mod), + [{unload,1,7,107}] = nif_mod_call_history(), + + 1 = nif_mod:lib_version(), + [{lib_version,1,8,108}] = nif_mod_call_history(), + + true = code:delete(nif_mod), + [] = nif_mod_call_history(), + + %% Repeat upgrade again but from old (deleted) instance + {module,nif_mod} = code:load_binary(nif_mod,File,Bin), + [{upgrade,1,9,109}] = nif_mod_call_history(), + 1 = nif_mod:lib_version(), + 1 = call(Pid,lib_version), + [{lib_version,1,10,110},{lib_version,1,11,111}] = nif_mod_call_history(), + + upgraded = call(Pid,upgrade), + false = check_process_code(Pid, nif_mod), + true = code:soft_purge(nif_mod), + [{unload,1,12,112}] = nif_mod_call_history(), + + 1 = nif_mod:lib_version(), + [{lib_version,1,13,113}] = nif_mod_call_history(), + + true = code:delete(nif_mod), + [] = nif_mod_call_history(), + + + Pid ! die, + {'DOWN', MRef, process, Pid, normal} = receive_any(), + false = check_process_code(Pid, nif_mod), + true = code:soft_purge(nif_mod), + [{unload,1,14,114}] = nif_mod_call_history(), + + %% Module upgrade with different lib version + {module,nif_mod} = code:load_binary(nif_mod,File,Bin), + hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()), + [{load,1,1,101},{get_priv_data_ptr,1,2,102}] = nif_mod_call_history(), + + 1 = nif_mod:lib_version(), + {Pid2,MRef2} = nif_mod:start(), + 1 = call(Pid2,lib_version), + [{lib_version,1,3,103},{lib_version,1,4,104}] = nif_mod_call_history(), + + true = ets:insert(nif_SUITE,{lib_version,2}), + {module,nif_mod} = code:load_binary(nif_mod,File,Bin), + [{upgrade,2,1,201}] = nif_mod_call_history(), + + 2 = nif_mod:lib_version(), + 1 = call(Pid2,lib_version), + [{lib_version,2,2,202},{lib_version,1,5,105}] = nif_mod_call_history(), + + upgraded = call(Pid2,upgrade), + false = check_process_code(Pid2, nif_mod), + true = code:soft_purge(nif_mod), + [{unload,1,6,106}] = nif_mod_call_history(), + + 2 = nif_mod:lib_version(), + 2 = call(Pid2,lib_version), + [{lib_version,2,3,203},{lib_version,2,4,204}] = nif_mod_call_history(), + + true = code:delete(nif_mod), + [] = nif_mod_call_history(), + + %% Reverse upgrade but from old (deleted) instance + ets:insert(nif_SUITE,{lib_version,1}), + {module,nif_mod} = code:load_binary(nif_mod,File,Bin), + [{upgrade,1,1,101}] = nif_mod_call_history(), + + 1 = nif_mod:lib_version(), + 2 = call(Pid2,lib_version), + [{lib_version,1,2,102},{lib_version,2,5,205}] = nif_mod_call_history(), + + upgraded = call(Pid2,upgrade), + false = check_process_code(Pid2, nif_mod), + true = code:soft_purge(nif_mod), + [{unload,2,6,206}] = nif_mod_call_history(), + + 1 = nif_mod:lib_version(), + [{lib_version,1,3,103}] = nif_mod_call_history(), + + true = code:delete(nif_mod), + [] = nif_mod_call_history(), + + + Pid2 ! die, + {'DOWN', MRef2, process, Pid2, normal} = receive_any(), + false= check_process_code(Pid2, nif_mod), + true = code:soft_purge(nif_mod), + [{unload,1,4,104}] = nif_mod_call_history(), + + true = lists:member(?MODULE, erlang:system_info(taints)), + true = lists:member(nif_mod, erlang:system_info(taints)), + verify_tmpmem(TmpMem), + ok. + + %% Test NIF building heap fragments heap_frag(Config) when is_list(Config) -> TmpMem = tmpmem(), diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.erl b/erts/emulator/test/nif_SUITE_data/nif_mod.erl index eec1bb8858..1fcc33faa4 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_mod.erl +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.erl @@ -29,6 +29,16 @@ -define(nif_stub,nif_stub_error(?LINE)). +-ifdef(USE_ON_LOAD). +-on_load(on_load/0). + +on_load() -> + [{data_dir, Path}] = ets:lookup(nif_SUITE, data_dir), + [{lib_version, Ver}] = ets:lookup(nif_SUITE, lib_version), + erlang:load_nif(filename:join(Path,libname(Ver)), []). + +-endif. + load_nif_lib(Config, Ver) -> load_nif_lib(Config, Ver, []). -- cgit v1.2.3 From 7262d8630998517e97ec62a7e0d9cbdd23fdd9c8 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 12 Sep 2016 15:05:47 +0200 Subject: erts: Fix trace_nif_SUITE to load nif lib only once --- erts/emulator/test/trace_nif_SUITE.erl | 12 +++++++++--- erts/emulator/test/trace_nif_SUITE_data/trace_nif.c | 11 ++++++----- 2 files changed, 15 insertions(+), 8 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/trace_nif_SUITE.erl b/erts/emulator/test/trace_nif_SUITE.erl index 8d5bff2a48..7ac6fce234 100644 --- a/erts/emulator/test/trace_nif_SUITE.erl +++ b/erts/emulator/test/trace_nif_SUITE.erl @@ -265,10 +265,16 @@ nif_process() -> nif_process(). load_nif(Config) -> - Path = proplists:get_value(data_dir, Config), - - ok = erlang:load_nif(filename:join(Path,"trace_nif"), 0). + case is_nif_loaded() of + true -> + ok; + false -> + Path = proplists:get_value(data_dir, Config), + ok = erlang:load_nif(filename:join(Path,"trace_nif"), 0) + end. +is_nif_loaded() -> + false. nif() -> {"Stub0",[]}. %exit("nif/0 stub called"). diff --git a/erts/emulator/test/trace_nif_SUITE_data/trace_nif.c b/erts/emulator/test/trace_nif_SUITE_data/trace_nif.c index 26f2420b8b..0c29ff8da8 100644 --- a/erts/emulator/test/trace_nif_SUITE_data/trace_nif.c +++ b/erts/emulator/test/trace_nif_SUITE_data/trace_nif.c @@ -6,18 +6,18 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) return 0; } -static int reload(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info) { return 0; } -static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info) +static void unload(ErlNifEnv* env, void* priv_data) { - return 0; } -static void unload(ErlNifEnv* env, void* priv_data) +static ERL_NIF_TERM is_nif_loaded(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { + return enif_make_atom(env,"true"); } static ERL_NIF_TERM nif_0(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) @@ -38,9 +38,10 @@ static ERL_NIF_TERM nif_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) static ErlNifFunc nif_funcs[] = { + {"is_nif_loaded", 0, is_nif_loaded}, {"nif", 0, nif_0}, {"nif", 1, nif_1} }; -ERL_NIF_INIT(trace_nif_SUITE,nif_funcs,load,reload,upgrade,unload) +ERL_NIF_INIT(trace_nif_SUITE,nif_funcs,load,NULL,upgrade,unload) -- cgit v1.2.3 From 4f8071d81aa0690caa3adc734d73a1cb004ad808 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 19 Sep 2016 14:34:57 +0200 Subject: erts: Remove deprecated nif 'reload' feature and instead let erlang:load_nif/2 return {error, {reload, _}} before even trying to load the library if a NIF library has already been successfully loaded for the calling module instance. --- erts/emulator/test/nif_SUITE.erl | 39 ++++++++++++++-------- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 10 +----- erts/emulator/test/nif_SUITE_data/tester.c | 4 +-- .../test/trace_call_time_SUITE_data/trace_nif.c | 7 +--- 4 files changed, 29 insertions(+), 31 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 9c1694fa8a..701b46665c 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -28,7 +28,7 @@ -export([all/0, suite/0, init_per_testcase/2, end_per_testcase/2, - basic/1, reload/1, upgrade/1, heap_frag/1, + basic/1, reload_error/1, upgrade/1, heap_frag/1, t_on_load/1, types/1, many_args/1, binaries/1, get_string/1, get_atom/1, maps/1, @@ -68,7 +68,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [basic, reload, upgrade, heap_frag, types, many_args, + [basic, reload_error, upgrade, heap_frag, types, many_args, t_on_load, binaries, get_string, get_atom, maps, api_macros, from_array, iolist_as_binary, resource, resource_binary, @@ -112,8 +112,8 @@ basic(Config) when is_list(Config) -> true = lists:member(?MODULE, erlang:system_info(taints)), ok. -%% Test reload callback in nif lib -reload(Config) when is_list(Config) -> +%% Test old reload feature now always fails +reload_error(Config) when is_list(Config) -> TmpMem = tmpmem(), ensure_lib_loaded(Config), @@ -127,20 +127,20 @@ reload(Config) when is_list(Config) -> hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()), [{load,1,1,101},{get_priv_data_ptr,1,2,102}] = nif_mod_call_history(), - ok = nif_mod:load_nif_lib(Config, 2), - 2 = nif_mod:lib_version(), - [{reload,2,1,201},{lib_version,2,2,202}] = nif_mod_call_history(), + {error, {reload, _}} = nif_mod:load_nif_lib(Config, 2), + 1 = nif_mod:lib_version(), + [{lib_version,1,3,103}] = nif_mod_call_history(), - ok = nif_mod:load_nif_lib(Config, 1), + {error, {reload, _}} = nif_mod:load_nif_lib(Config, 1), 1 = nif_mod:lib_version(), - [{reload,1,1,101},{lib_version,1,2,102}] = nif_mod_call_history(), + [{lib_version,1,4,104}] = nif_mod_call_history(), true = erlang:delete_module(nif_mod), [] = nif_mod_call_history(), %%false= check_process_code(Pid, nif_mod), true = erlang:purge_module(nif_mod), - [{unload,1,3,103}] = nif_mod_call_history(), + [{unload,1,5,105}] = nif_mod_call_history(), true = lists:member(?MODULE, erlang:system_info(taints)), true = lists:member(nif_mod, erlang:system_info(taints)), @@ -828,7 +828,7 @@ resource_binary_do() -> -define(RT_CREATE,1). -define(RT_TAKEOVER,2). -%% Test resource takeover by module reload and upgrade +%% Test resource takeover by module upgrade resource_takeover(Config) when is_list(Config) -> TmpMem = tmpmem(), ensure_lib_loaded(Config), @@ -893,6 +893,7 @@ resource_takeover(Config) when is_list(Config) -> ok = forget_resource(NGX1), ?CHECK([], nif_mod_call_history()), % no dtor + {module,nif_mod} = erlang:load_module(nif_mod,ModBin), ok = nif_mod:load_nif_lib(Config, 2, [{resource_type, 0, ?RT_TAKEOVER, "resource_type_A",resource_dtor_A, ?RT_TAKEOVER}, @@ -911,7 +912,9 @@ resource_takeover(Config) when is_list(Config) -> {resource_type, 4, ?RT_CREATE, "resource_type_null_goneY",null, ?RT_CREATE} ]), - ?CHECK([{reload,2,1,201}], nif_mod_call_history()), + ?CHECK([{upgrade,2,1,201}], nif_mod_call_history()), + true = erlang:purge_module(nif_mod), + ?CHECK([{unload,1,1,106}], nif_mod_call_history()), BinA2 = read_resource(0,A2), ok = forget_resource(A2), @@ -1221,11 +1224,19 @@ threading_do(Config) -> ok = tester:load_nif_lib(Config, "basic"), ok = tester:run(), + erlang:load_module(tester,ModBin), + erlang:purge_module(tester), ok = tester:load_nif_lib(Config, "rwlock"), ok = tester:run(), + erlang:load_module(tester,ModBin), + erlang:purge_module(tester), ok = tester:load_nif_lib(Config, "tsd"), - ok = tester:run(). + ok = tester:run(), + + erlang:delete_module(tester), + erlang:purge_module(tester). + %% Test NIF message sending send(Config) when is_list(Config) -> @@ -1513,13 +1524,13 @@ send3_new_state(State, Blob) -> neg(Config) when is_list(Config) -> TmpMem = tmpmem(), {'EXIT',{badarg,_}} = (catch erlang:load_nif(badarg, 0)), - {error,{load_failed,_}} = erlang:load_nif("pink_unicorn", 0), Data = proplists:get_value(data_dir, Config), File = filename:join(Data, "nif_mod"), {ok,nif_mod,Bin} = compile:file(File, [binary,return_errors]), {module,nif_mod} = erlang:load_module(nif_mod,Bin), + {error,{load_failed,_}} = nif_mod:load_nif_lib(Config, 0), {error,{bad_lib,_}} = nif_mod:load_nif_lib(Config, no_init), verify_tmpmem(TmpMem), ok. diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index f2b1ef9d24..99534a9694 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -184,14 +184,6 @@ static void resource_takeover(ErlNifEnv* env, PrivData* priv) msgenv_resource_type = rt; } -static int reload(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) -{ - PrivData* priv = (PrivData*) *priv_data; - add_call(env, priv, "reload"); - resource_takeover(env,priv); - return 0; -} - static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info) { PrivData* priv = (PrivData*) *old_priv_data; @@ -2094,4 +2086,4 @@ static ErlNifFunc nif_funcs[] = {"format_term_nif", 2, format_term} }; -ERL_NIF_INIT(nif_SUITE,nif_funcs,load,reload,upgrade,unload) +ERL_NIF_INIT(nif_SUITE,nif_funcs,load,NULL,upgrade,unload) diff --git a/erts/emulator/test/nif_SUITE_data/tester.c b/erts/emulator/test/nif_SUITE_data/tester.c index 257b116322..9e0074d554 100644 --- a/erts/emulator/test/nif_SUITE_data/tester.c +++ b/erts/emulator/test/nif_SUITE_data/tester.c @@ -53,7 +53,7 @@ void testcase_free(void *ptr) void testcase_run(TestCaseState_t *tcs); -static int reload(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info) { return 0; } @@ -70,5 +70,5 @@ static ErlNifFunc nif_funcs[] = {"run", 0, run} }; -ERL_NIF_INIT(tester,nif_funcs,NULL,reload,NULL,NULL) +ERL_NIF_INIT(tester,nif_funcs,NULL,NULL,upgrade,NULL) diff --git a/erts/emulator/test/trace_call_time_SUITE_data/trace_nif.c b/erts/emulator/test/trace_call_time_SUITE_data/trace_nif.c index 33b346aab7..0540c25cb9 100644 --- a/erts/emulator/test/trace_call_time_SUITE_data/trace_nif.c +++ b/erts/emulator/test/trace_call_time_SUITE_data/trace_nif.c @@ -6,11 +6,6 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) return 0; } -static int reload(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) -{ - return 0; -} - static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info) { return 0; @@ -34,4 +29,4 @@ static ErlNifFunc nif_funcs[] = {"nif_dec", 1, nif_dec_1} }; -ERL_NIF_INIT(trace_call_time_SUITE,nif_funcs,load,reload,upgrade,unload) +ERL_NIF_INIT(trace_call_time_SUITE,nif_funcs,load,NULL,upgrade,unload) -- cgit v1.2.3 From a54773f05cd60045a4ac0f9a4ae753aa76185b61 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 9 Sep 2016 16:15:52 +0200 Subject: erts: Cuddle nif_SUITE:consume_timeslice --- erts/emulator/test/nif_SUITE.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 701b46665c..306f2091a1 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -1651,6 +1651,7 @@ consume_timeslice(Config) when is_list(Config) -> end. consume_timeslice_test(Config) when is_list(Config) -> + ensure_lib_loaded(Config), CONTEXT_REDS = 2000, Me = self(), Go = make_ref(), @@ -1727,7 +1728,7 @@ consume_timeslice_test(Config) when is_list(Config) -> io:format("Reductions = ~p~n", [Reductions]), ok; {RedDiff, Reductions} -> - ct:fail({unexpected_reduction_count, Reductions}) + ct:fail({unexpected_reduction_count, Reductions, ExpReds}) end, none = next_msg(P), -- cgit v1.2.3 From 3489b9b689073f428a23f7fc7a67774b7dda07be Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Sun, 18 Sep 2016 12:33:08 +0200 Subject: Use more correct delimiters for erl_nif.h include Anywhere but the beam sources we shouldn't #include "erl_nif.h", because what "erl_nif.h" does is: (1) fail to find it outside of -I dirs, (2) then treat it as if it was written like . Using skips (1). More information can be found in 6.10.2 of the C standard. Because the examples use "erl_nif.h", NIF projects in the Erlang ecosystem copy this verbatim and make the same mistake. --- erts/emulator/test/alloc_SUITE_data/testcase_driver.h | 2 +- erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c | 2 +- erts/emulator/test/mtx_SUITE_data/mtx_SUITE.c | 2 +- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 2 +- erts/emulator/test/nif_SUITE_data/nif_mod.c | 2 +- erts/emulator/test/nif_SUITE_data/testcase_driver.h | 2 +- erts/emulator/test/nif_SUITE_data/tester.c | 2 +- erts/emulator/test/trace_call_time_SUITE_data/trace_nif.c | 2 +- erts/emulator/test/trace_nif_SUITE_data/trace_nif.c | 2 +- erts/emulator/test/tracer_SUITE_data/tracer_test.c | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/alloc_SUITE_data/testcase_driver.h b/erts/emulator/test/alloc_SUITE_data/testcase_driver.h index f0ca91bd06..2b742dd7e3 100644 --- a/erts/emulator/test/alloc_SUITE_data/testcase_driver.h +++ b/erts/emulator/test/alloc_SUITE_data/testcase_driver.h @@ -20,7 +20,7 @@ #ifndef TESTCASE_DRIVER_H__ #define TESTCASE_DRIVER_H__ -#include "erl_nif.h" +#include #include typedef struct { diff --git a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c index a0019e5d95..daaff955bc 100644 --- a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c +++ b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c @@ -17,7 +17,7 @@ * * %CopyrightEnd% */ -#include "erl_nif.h" +#include #include #ifdef __WIN32__ #include diff --git a/erts/emulator/test/mtx_SUITE_data/mtx_SUITE.c b/erts/emulator/test/mtx_SUITE_data/mtx_SUITE.c index e011aadce9..46ee8b5540 100644 --- a/erts/emulator/test/mtx_SUITE_data/mtx_SUITE.c +++ b/erts/emulator/test/mtx_SUITE_data/mtx_SUITE.c @@ -24,7 +24,7 @@ * Author: Rickard Green */ -#include "erl_nif.h" +#include #ifdef __WIN32__ # ifndef WIN32_LEAN_AND_MEAN diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index f2b1ef9d24..ed142478c6 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -17,7 +17,7 @@ * * %CopyrightEnd% */ -#include "erl_nif.h" +#include #include #include diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.c b/erts/emulator/test/nif_SUITE_data/nif_mod.c index fd8a0d0595..4e94e7901c 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_mod.c +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.c @@ -17,7 +17,7 @@ * * %CopyrightEnd% */ -#include "erl_nif.h" +#include #include #include diff --git a/erts/emulator/test/nif_SUITE_data/testcase_driver.h b/erts/emulator/test/nif_SUITE_data/testcase_driver.h index e32e63069a..feb10ecaea 100644 --- a/erts/emulator/test/nif_SUITE_data/testcase_driver.h +++ b/erts/emulator/test/nif_SUITE_data/testcase_driver.h @@ -20,7 +20,7 @@ #ifndef TESTCASE_DRIVER_H__ #define TESTCASE_DRIVER_H__ -#include "erl_nif.h" +#include #include #include diff --git a/erts/emulator/test/nif_SUITE_data/tester.c b/erts/emulator/test/nif_SUITE_data/tester.c index 257b116322..248c31fd3a 100644 --- a/erts/emulator/test/nif_SUITE_data/tester.c +++ b/erts/emulator/test/nif_SUITE_data/tester.c @@ -1,4 +1,4 @@ -#include "erl_nif.h" +#include #include #include diff --git a/erts/emulator/test/trace_call_time_SUITE_data/trace_nif.c b/erts/emulator/test/trace_call_time_SUITE_data/trace_nif.c index 33b346aab7..b8c8590546 100644 --- a/erts/emulator/test/trace_call_time_SUITE_data/trace_nif.c +++ b/erts/emulator/test/trace_call_time_SUITE_data/trace_nif.c @@ -1,4 +1,4 @@ -#include "erl_nif.h" +#include static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) diff --git a/erts/emulator/test/trace_nif_SUITE_data/trace_nif.c b/erts/emulator/test/trace_nif_SUITE_data/trace_nif.c index 26f2420b8b..fe9308bf4e 100644 --- a/erts/emulator/test/trace_nif_SUITE_data/trace_nif.c +++ b/erts/emulator/test/trace_nif_SUITE_data/trace_nif.c @@ -1,4 +1,4 @@ -#include "erl_nif.h" +#include static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) diff --git a/erts/emulator/test/tracer_SUITE_data/tracer_test.c b/erts/emulator/test/tracer_SUITE_data/tracer_test.c index a26bb33600..b68e480215 100644 --- a/erts/emulator/test/tracer_SUITE_data/tracer_test.c +++ b/erts/emulator/test/tracer_SUITE_data/tracer_test.c @@ -18,7 +18,7 @@ * %CopyrightEnd% */ -#include "erl_nif.h" +#include #include #include -- cgit v1.2.3 From b001b56e061454f3175d9d9a99e2efb945a696b9 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 4 Oct 2016 10:24:56 +0200 Subject: erts: Do tracer liveness check on current tracer This fixes a fault introduced in 19.0 where an invalid tracer would block setting of a new tracer on a process. --- erts/emulator/test/trace_SUITE.erl | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/trace_SUITE.erl b/erts/emulator/test/trace_SUITE.erl index da6a6bdea4..f846b0f4b9 100644 --- a/erts/emulator/test/trace_SUITE.erl +++ b/erts/emulator/test/trace_SUITE.erl @@ -30,7 +30,7 @@ procs_trace/1, dist_procs_trace/1, procs_new_trace/1, suspend/1, mutual_suspend/1, suspend_exit/1, suspender_exit/1, suspend_system_limit/1, suspend_opts/1, suspend_waiting/1, - new_clear/1, existing_clear/1, + new_clear/1, existing_clear/1, tracer_die/1, set_on_spawn/1, set_on_first_spawn/1, cpu_timestamp/1, set_on_link/1, set_on_first_link/1, system_monitor_args/1, more_system_monitor_args/1, @@ -54,7 +54,7 @@ all() -> send_trace, procs_trace, dist_procs_trace, suspend, mutual_suspend, suspend_exit, suspender_exit, suspend_system_limit, suspend_opts, suspend_waiting, - new_clear, existing_clear, set_on_spawn, + new_clear, existing_clear, tracer_die, set_on_spawn, set_on_first_spawn, set_on_link, set_on_first_link, system_monitor_args, more_system_monitor_args, system_monitor_long_gc_1, @@ -1636,6 +1636,34 @@ existing_clear(Config) when is_list(Config) -> ok. +%% Test that erlang:trace/3 can be called on processes where the +%% tracer has died. OTP-13928 +tracer_die(Config) when is_list(Config) -> + Proc = spawn(fun receiver/0), + + Tracer = spawn(fun receiver/0), + timer:sleep(1), + N = erlang:trace(existing, true, [send, {tracer, Tracer}]), + {flags, [send]} = erlang:trace_info(Proc, flags), + {tracer, Tracer} = erlang:trace_info(Proc, tracer), + exit(Tracer, die), + + Tracer2 = spawn(fun receiver/0), + timer:sleep(1), + N = erlang:trace(existing, true, [send, {tracer, Tracer2}]), + {flags, [send]} = erlang:trace_info(Proc, flags), + {tracer, Tracer2} = erlang:trace_info(Proc, tracer), + exit(Tracer2, die), + + Tracer3 = spawn(fun receiver/0), + timer:sleep(1), + 1 = erlang:trace(Proc, true, [send, {tracer, Tracer3}]), + {flags, [send]} = erlang:trace_info(Proc, flags), + {tracer, Tracer3} = erlang:trace_info(Proc, tracer), + exit(Tracer3, die), + + ok. + %% Test that an invalid flag cause badarg bad_flag(Config) when is_list(Config) -> %% A bad flag could deadlock the SMP emulator in erts-5.5 -- cgit v1.2.3 From 099c60de4033d7b397d4b3fb47f183b52fcba855 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 15 Sep 2016 21:21:10 +0200 Subject: erts: Improve hipe load/upgrade/purge machinery A step toward better integration of hipe load and purge Highlights: * code_server no longer needs to call hipe_unified_loader:post_beam_load/1 Instead new internal function hipe_redirect_to_module() is called by loading BIFs to patch native call sites if needed. * hipe_purge_module() is called by erts_internal:purge_module/2 to purge any native code. * struct hipe_mfa_info redesigned and only used for exported functions that are called from or implemented by native code. A list of native call sites (struct hipe_ref) are kept for each hipe_mfa_info. * struct hipe_sdesc used by hipe_find_mfa_from_ra() to build native stack traces. --- erts/emulator/test/code_SUITE.erl | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index 8427bb134d..b76ba6427f 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -445,62 +445,64 @@ module_md5_ok(Code) -> make_stub(Config) when is_list(Config) -> catch erlang:purge_module(my_code_test), MD5 = erlang:md5(<<>>), + Arg3 = {[], [], MD5, 0, 0}, Data = proplists:get_value(data_dir, Config), File = filename:join(Data, "my_code_test"), {ok,my_code_test,Code} = compile:file(File, [binary]), - my_code_test = code:make_stub_module(my_code_test, Code, {[],[],MD5}), + my_code_test = code:make_stub_module(my_code_test, Code, Arg3), true = erlang:delete_module(my_code_test), true = erlang:purge_module(my_code_test), my_code_test = code:make_stub_module(my_code_test, make_unaligned_sub_binary(Code), - {[],[],MD5}), + Arg3), true = erlang:delete_module(my_code_test), true = erlang:purge_module(my_code_test), my_code_test = code:make_stub_module(my_code_test, zlib:gzip(Code), - {[],[],MD5}), + Arg3), true = erlang:delete_module(my_code_test), true = erlang:purge_module(my_code_test), %% Should fail. {'EXIT',{badarg,_}} = - (catch code:make_stub_module(my_code_test, <<"bad">>, {[],[],MD5})), + (catch code:make_stub_module(my_code_test, <<"bad">>, Arg3)), {'EXIT',{badarg,_}} = (catch code:make_stub_module(my_code_test, bit_sized_binary(Code), - {[],[],MD5})), + Arg3)), {'EXIT',{badarg,_}} = (catch code:make_stub_module(my_code_test_with_wrong_name, - Code, {[],[],MD5})), + Code, Arg3)), ok. make_stub_many_funs(Config) when is_list(Config) -> catch erlang:purge_module(many_funs), MD5 = erlang:md5(<<>>), + Arg3 = {[], [], MD5, 0, 0}, Data = proplists:get_value(data_dir, Config), File = filename:join(Data, "many_funs"), {ok,many_funs,Code} = compile:file(File, [binary]), - many_funs = code:make_stub_module(many_funs, Code, {[],[],MD5}), + many_funs = code:make_stub_module(many_funs, Code, Arg3), true = erlang:delete_module(many_funs), true = erlang:purge_module(many_funs), many_funs = code:make_stub_module(many_funs, make_unaligned_sub_binary(Code), - {[],[],MD5}), + Arg3), true = erlang:delete_module(many_funs), true = erlang:purge_module(many_funs), %% Should fail. {'EXIT',{badarg,_}} = - (catch code:make_stub_module(many_funs, <<"bad">>, {[],[],MD5})), + (catch code:make_stub_module(many_funs, <<"bad">>, Arg3)), {'EXIT',{badarg,_}} = (catch code:make_stub_module(many_funs, bit_sized_binary(Code), - {[],[],MD5})), + Arg3)), ok. constant_pools(Config) when is_list(Config) -> -- cgit v1.2.3 From 2dfca60a24c2c6728a4b8431f37aeee05212a4ac Mon Sep 17 00:00:00 2001 From: Gabriele Santomaggio Date: Thu, 13 Oct 2016 21:17:10 +0200 Subject: Add system_info(atom_limit) Add system_info(atom_limit) to provide a way to retrieve the maximum number of atoms allowed. Add tests and documentation for it too. Also split system_info_SUITE:start_node/2 to start_node_ets/2 and start_node_atm/2 to avoid code duplication. --- erts/emulator/test/system_info_SUITE.erl | 59 +++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 12 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl index a4aedb31f6..3d9e74472b 100644 --- a/erts/emulator/test/system_info_SUITE.erl +++ b/erts/emulator/test/system_info_SUITE.erl @@ -36,7 +36,7 @@ -export([all/0, suite/0]). -export([process_count/1, system_version/1, misc_smoke_tests/1, - heap_size/1, wordsize/1, memory/1, ets_limit/1]). + heap_size/1, wordsize/1, memory/1, ets_limit/1, atom_limit/1]). suite() -> [{ct_hooks,[ts_install_cth]}, @@ -44,7 +44,7 @@ suite() -> all() -> [process_count, system_version, misc_smoke_tests, - heap_size, wordsize, memory, ets_limit]. + heap_size, wordsize, memory, ets_limit, atom_limit]. %%% %%% The test cases ------------------------------------------------------------- @@ -472,6 +472,17 @@ mapn(_Fun, 0) -> mapn(Fun, N) -> [Fun(N) | mapn(Fun, N-1)]. + +get_node_name(Config) -> + list_to_atom(atom_to_list(?MODULE) + ++ "-" + ++ atom_to_list(proplists:get_value(testcase, Config)) + ++ "-" + ++ integer_to_list(erlang:system_time(second)) + ++ "-" + ++ integer_to_list(erlang:unique_integer([positive]))). + + %% Verify system_info(ets_limit) reflects max ETS table settings. ets_limit(Config0) when is_list(Config0) -> Config = [{testcase,ets_limit}|Config0], @@ -486,7 +497,7 @@ get_ets_limit(Config, EtsMax) -> 0 -> []; _ -> [{"ERL_MAX_ETS_TABLES", integer_to_list(EtsMax)}] end, - {ok, Node} = start_node(Config, Envs), + {ok, Node} = start_node_ets(Config, Envs), Me = self(), Ref = make_ref(), spawn_link(Node, @@ -502,16 +513,40 @@ get_ets_limit(Config, EtsMax) -> stop_node(Node), Res. -start_node(Config, Envs) when is_list(Config) -> +start_node_ets(Config, Envs) when is_list(Config) -> + Pa = filename:dirname(code:which(?MODULE)), + test_server:start_node(get_node_name(Config), peer, + [{args, "-pa "++Pa}, {env, Envs}]). + +start_node_atm(Config, AtomsMax) when is_list(Config) -> Pa = filename:dirname(code:which(?MODULE)), - Name = list_to_atom(atom_to_list(?MODULE) - ++ "-" - ++ atom_to_list(proplists:get_value(testcase, Config)) - ++ "-" - ++ integer_to_list(erlang:system_time(second)) - ++ "-" - ++ integer_to_list(erlang:unique_integer([positive]))), - test_server:start_node(Name, peer, [{args, "-pa "++Pa}, {env, Envs}]). + test_server:start_node(get_node_name(Config), peer, + [{args, "-pa "++ Pa ++ AtomsMax}]). stop_node(Node) -> test_server:stop_node(Node). + + +%% Verify system_info(atom_limit) reflects max atoms settings +%% (using " +t"). +atom_limit(Config0) when is_list(Config0) -> + Config = [{testcase,atom_limit}|Config0], + 2186042 = get_atom_limit(Config, " +t 2186042 "), + ok. + +get_atom_limit(Config, AtomsMax) -> + {ok, Node} = start_node_atm(Config, AtomsMax), + Me = self(), + Ref = make_ref(), + spawn_link(Node, + fun() -> + Res = erlang:system_info(atom_limit), + unlink(Me), + Me ! {Ref, Res} + end), + receive + {Ref, Res} -> + Res + end, + stop_node(Node), + Res. -- cgit v1.2.3 From 5e879fb1d4a9273f0a6183da7509dcdbc24f9653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Fri, 16 Sep 2016 19:33:38 +0200 Subject: erts: Check hipe stack in check_process_code This is part of commit 1bd508921dd93086b05e7d0038b816b36c421d86. I did not include the fun-checking as we have a new purge strategy for funs in OTP 20. That remains to be solved some other way for hipe. --- erts/emulator/test/hipe_SUITE.erl | 57 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/hipe_SUITE.erl b/erts/emulator/test/hipe_SUITE.erl index a556b4ddc0..0b44dd7fb7 100644 --- a/erts/emulator/test/hipe_SUITE.erl +++ b/erts/emulator/test/hipe_SUITE.erl @@ -19,12 +19,17 @@ %% -module(hipe_SUITE). --export([all/0, t_copy_literals/1]). +-export([all/0 + ,t_copy_literals/1 + ,t_purge/1 + ]). all() -> case erlang:system_info(hipe_architecture) of undefined -> {skip, "HiPE is disabled"}; - _ -> [t_copy_literals] + _ -> [t_copy_literals + ,t_purge + ] end. t_copy_literals(doc) -> @@ -65,3 +70,51 @@ t_copy_literals(Config) when is_list(Config) -> true = erlang:delete_module(ref_cell), true = erlang:purge_module(ref_cell), ok. + +t_purge(doc) -> "Checks that native code is properly found and purged"; +t_purge(Config) when is_list(Config) -> + Data = proplists:get_value(data_dir, Config), + Priv = proplists:get_value(priv_dir, Config), + SrcFile = filename:join(Data, "ref_cell"), + BeamFile = filename:join(Priv, "ref_cell"), + {ok,ref_cell} = c:c(SrcFile, [{outdir,Priv},native]), + true = code:is_module_native(ref_cell), + + PA = ref_cell:start_link(), + + %% Unload, PA should still be running + true = erlang:delete_module(ref_cell), + %% Can't use ref_cel:call/2, it's in old code! + call(PA, {put_res_of, fun()-> hej end}), + hej = call(PA, get), + + %% Load same module again + code:load_abs(BeamFile), + true = code:is_module_native(ref_cell), + PB = ref_cell:start_link(), + + %% Purge old code, PA should be killed, PB should survive + unlink(PA), + ARef = monitor(process, PA), + true = erlang:purge_module(ref_cell), + receive {'DOWN', ARef, process, PA, killed} -> ok + after 1 -> ct:fail("PA was not killed") + end, + + %% Unload, PB should still be running + true = erlang:delete_module(ref_cell), + call(PB, {put_res_of, fun()-> svejs end}), + svejs = call(PB, get), + + unlink(PB), + BRef = monitor(process, PB), + true = erlang:purge_module(ref_cell), + receive {'DOWN', BRef, process, PB, killed} -> ok + after 1 -> ct:fail("PB was not killed") + end, + + ok. + +call(Pid, Call) -> + Pid ! {Call, self()}, + receive {Pid, Res} -> Res end. -- cgit v1.2.3 From 9aa58e5e93af074d1e5e54848c29d40d826de361 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 7 Oct 2016 16:18:07 +0200 Subject: erts: Remove code_SUITE:make_stub and make_stub_many_funs Hard to unit test now when it takes a magic HipeLoaderState as argument. All hipe testing should be enough exercise for code:make_stub_module. --- erts/emulator/test/code_SUITE.erl | 69 ++------------------------------------- 1 file changed, 3 insertions(+), 66 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index b76ba6427f..465ddfa7a8 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -23,8 +23,8 @@ versions/1,new_binary_types/1, call_purged_fun_code_gone/1, call_purged_fun_code_reload/1, call_purged_fun_code_there/1, multi_proc_purge/1, t_check_old_code/1, - external_fun/1,get_chunk/1,module_md5/1,make_stub/1, - make_stub_many_funs/1,constant_pools/1,constant_refc_binaries/1, + external_fun/1,get_chunk/1,module_md5/1, + constant_pools/1,constant_refc_binaries/1, false_dependency/1,coverage/1,fun_confusion/1, t_copy_literals/1, t_copy_literals_frags/1]). @@ -37,7 +37,7 @@ all() -> [versions, new_binary_types, call_purged_fun_code_gone, call_purged_fun_code_reload, call_purged_fun_code_there, multi_proc_purge, t_check_old_code, external_fun, get_chunk, - module_md5, make_stub, make_stub_many_funs, + module_md5, constant_pools, constant_refc_binaries, false_dependency, coverage, fun_confusion, t_copy_literals, t_copy_literals_frags]. @@ -442,69 +442,6 @@ module_md5_ok(Code) -> end. -make_stub(Config) when is_list(Config) -> - catch erlang:purge_module(my_code_test), - MD5 = erlang:md5(<<>>), - Arg3 = {[], [], MD5, 0, 0}, - - Data = proplists:get_value(data_dir, Config), - File = filename:join(Data, "my_code_test"), - {ok,my_code_test,Code} = compile:file(File, [binary]), - - my_code_test = code:make_stub_module(my_code_test, Code, Arg3), - true = erlang:delete_module(my_code_test), - true = erlang:purge_module(my_code_test), - - my_code_test = code:make_stub_module(my_code_test, - make_unaligned_sub_binary(Code), - Arg3), - true = erlang:delete_module(my_code_test), - true = erlang:purge_module(my_code_test), - - my_code_test = code:make_stub_module(my_code_test, zlib:gzip(Code), - Arg3), - true = erlang:delete_module(my_code_test), - true = erlang:purge_module(my_code_test), - - %% Should fail. - {'EXIT',{badarg,_}} = - (catch code:make_stub_module(my_code_test, <<"bad">>, Arg3)), - {'EXIT',{badarg,_}} = - (catch code:make_stub_module(my_code_test, - bit_sized_binary(Code), - Arg3)), - {'EXIT',{badarg,_}} = - (catch code:make_stub_module(my_code_test_with_wrong_name, - Code, Arg3)), - ok. - -make_stub_many_funs(Config) when is_list(Config) -> - catch erlang:purge_module(many_funs), - MD5 = erlang:md5(<<>>), - Arg3 = {[], [], MD5, 0, 0}, - - Data = proplists:get_value(data_dir, Config), - File = filename:join(Data, "many_funs"), - {ok,many_funs,Code} = compile:file(File, [binary]), - - many_funs = code:make_stub_module(many_funs, Code, Arg3), - true = erlang:delete_module(many_funs), - true = erlang:purge_module(many_funs), - many_funs = code:make_stub_module(many_funs, - make_unaligned_sub_binary(Code), - Arg3), - true = erlang:delete_module(many_funs), - true = erlang:purge_module(many_funs), - - %% Should fail. - {'EXIT',{badarg,_}} = - (catch code:make_stub_module(many_funs, <<"bad">>, Arg3)), - {'EXIT',{badarg,_}} = - (catch code:make_stub_module(many_funs, - bit_sized_binary(Code), - Arg3)), - ok. - constant_pools(Config) when is_list(Config) -> Data = proplists:get_value(data_dir, Config), File = filename:join(Data, "literals"), -- cgit v1.2.3 From c5aa2c8a4e943176e5e7dea7c8653aee93faa18e Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 26 Oct 2016 17:49:44 +0200 Subject: erts: Expand purge fun tests for hipe --- erts/emulator/test/code_SUITE.erl | 168 ++------------------- .../code_SUITE_data/call_purged_fun_tester.erl | 167 ++++++++++++++++++++ 2 files changed, 183 insertions(+), 152 deletions(-) create mode 100644 erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index 465ddfa7a8..774461c525 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -153,127 +153,23 @@ call_purged_fun_code_there(Config) when is_list(Config) -> ok. call_purged_fun_test(Priv, Data, Type) -> - File = filename:join(Data, "my_code_test2"), - Code = filename:join(Priv, "my_code_test2"), - - catch erlang:purge_module(my_code_test2), - catch erlang:delete_module(my_code_test2), - catch erlang:purge_module(my_code_test2), - - {ok,my_code_test2} = c:c(File, [{outdir,Priv}]), - - T = ets:new(my_code_test2_fun_table, []), - ets:insert(T, {my_fun,my_code_test2:make_fun(4711)}), - ets:insert(T, {my_fun2,my_code_test2:make_fun2()}), - - spawn(fun () -> - [{my_fun2,F2}] = ets:lookup(T, my_fun2), - F2(fun () -> - receive after infinity -> ok end - end, - fun () -> ok end), - exit(completed) - end), - - PurgeType = case Type of - code_gone -> - ok = file:delete(Code++".beam"), - true; - code_reload -> - true; - code_there -> - false - end, - - true = erlang:delete_module(my_code_test2), - - Purge = start_purge(my_code_test2, PurgeType), - - {P0, M0} = spawn_monitor(fun () -> - [{my_fun,F}] = ets:lookup(T, my_fun), - 4712 = F(1), - exit(completed) - end), - - wait_until(fun () -> - {status, suspended} - == process_info(P0, status) - end), - - ok = continue_purge(Purge), - - {P1, M1} = spawn_monitor(fun () -> - [{my_fun,F}] = ets:lookup(T, my_fun), - 4713 = F(2), - exit(completed) - end), - {P2, M2} = spawn_monitor(fun () -> - [{my_fun,F}] = ets:lookup(T, my_fun), - 4714 = F(3), - exit(completed) - end), - - wait_until(fun () -> - {status, suspended} - == process_info(P1, status) - end), - wait_until(fun () -> - {status, suspended} - == process_info(P2, status) - end), - - {current_function, - {erts_code_purger, - pending_purge_lambda, - 3}} = process_info(P0, current_function), - {current_function, - {erts_code_purger, - pending_purge_lambda, - 3}} = process_info(P1, current_function), - {current_function, - {erts_code_purger, - pending_purge_lambda, - 3}} = process_info(P2, current_function), - - case Type of - code_there -> - false = complete_purge(Purge); - _ -> - {true, true} = complete_purge(Purge) - end, + OptsList = case erlang:system_info(hipe_architecture) of + undefined -> [[]]; + _ -> [[], [native]] + end, + [call_purged_fun_test_do(Priv, Data, Type, CO, FO) + || CO <- OptsList, FO <- OptsList]. + + +call_purged_fun_test_do(Priv, Data, Type, CallerOpts, FunOpts) -> + io:format("Compile caller as ~p and funs as ~p\n", [CallerOpts, FunOpts]), + SrcFile = filename:join(Data, "call_purged_fun_tester.erl"), + ObjFile = filename:join(Priv, "call_purged_fun_tester.beam"), + {ok,Mod,Code} = compile:file(SrcFile, [binary, report | CallerOpts]), + {module,Mod} = code:load_binary(Mod, ObjFile, Code), + + call_purged_fun_tester:do(Priv, Data, Type, FunOpts). - case Type of - code_gone -> - receive - {'DOWN', M0, process, P0, Reason0} -> - {undef, _} = Reason0 - end, - receive - {'DOWN', M1, process, P1, Reason1} -> - {undef, _} = Reason1 - end, - receive - {'DOWN', M2, process, P2, Reason2} -> - {undef, _} = Reason2 - end; - _ -> - receive - {'DOWN', M0, process, P0, Reason0} -> - completed = Reason0 - end, - receive - {'DOWN', M1, process, P1, Reason1} -> - completed = Reason1 - end, - receive - {'DOWN', M2, process, P2, Reason2} -> - completed = Reason2 - end, - catch erlang:purge_module(my_code_test2), - catch erlang:delete_module(my_code_test2), - catch erlang:purge_module(my_code_test2) - end, - ok. multi_proc_purge(Config) when is_list(Config) -> %% @@ -975,35 +871,3 @@ flush() -> id(I) -> I. -wait_until(Fun) -> - case Fun() of - true -> - ok; - false -> - receive after 100 -> ok end, - wait_until(Fun) - end. - -start_purge(Mod, Type) when is_atom(Mod) - andalso ((Type == true) - orelse (Type == false)) -> - Ref = make_ref(), - erts_code_purger ! {test_purge, Mod, self(), Type, Ref}, - receive - {started, Ref} -> - Ref - end. - -continue_purge(Ref) when is_reference(Ref) -> - erts_code_purger ! {continue, Ref}, - receive - {continued, Ref} -> - ok - end. - -complete_purge(Ref) when is_reference(Ref) -> - erts_code_purger ! {complete, Ref}, - receive - {test_purge, Res, Ref} -> - Res - end. diff --git a/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl b/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl new file mode 100644 index 0000000000..5e031abca8 --- /dev/null +++ b/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl @@ -0,0 +1,167 @@ +-module(call_purged_fun_tester). + +-export([do/4]). + +do(Priv, Data, Type, Opts) -> + File = filename:join(Data, "my_code_test2"), + Code = filename:join(Priv, "my_code_test2"), + + catch erlang:purge_module(my_code_test2), + catch erlang:delete_module(my_code_test2), + catch erlang:purge_module(my_code_test2), + + {ok,my_code_test2} = c:c(File, [{outdir,Priv} | Opts]), + + IsNative = lists:member(native,Opts), + IsNative = code:is_module_native(my_code_test2), + + T = ets:new(my_code_test2_fun_table, []), + ets:insert(T, {my_fun,my_code_test2:make_fun(4711)}), + ets:insert(T, {my_fun2,my_code_test2:make_fun2()}), + + spawn(fun () -> + [{my_fun2,F2}] = ets:lookup(T, my_fun2), + F2(fun () -> + receive after infinity -> ok end + end, + fun () -> ok end), + exit(completed) + end), + + PurgeType = case Type of + code_gone -> + ok = file:delete(Code++".beam"), + true; + code_reload -> + true; + code_there -> + false + end, + + true = erlang:delete_module(my_code_test2), + + Purge = start_purge(my_code_test2, PurgeType), + + {P0, M0} = spawn_monitor(fun () -> + [{my_fun,F}] = ets:lookup(T, my_fun), + 4712 = F(1), + exit(completed) + end), + + wait_until(fun () -> + {status, suspended} + == process_info(P0, status) + end), + + ok = continue_purge(Purge), + + {P1, M1} = spawn_monitor(fun () -> + [{my_fun,F}] = ets:lookup(T, my_fun), + 4713 = F(2), + exit(completed) + end), + {P2, M2} = spawn_monitor(fun () -> + [{my_fun,F}] = ets:lookup(T, my_fun), + 4714 = F(3), + exit(completed) + end), + + wait_until(fun () -> + {status, suspended} + == process_info(P1, status) + end), + wait_until(fun () -> + {status, suspended} + == process_info(P2, status) + end), + + {current_function, + {erts_code_purger, + pending_purge_lambda, + 3}} = process_info(P0, current_function), + {current_function, + {erts_code_purger, + pending_purge_lambda, + 3}} = process_info(P1, current_function), + {current_function, + {erts_code_purger, + pending_purge_lambda, + 3}} = process_info(P2, current_function), + + case Type of + code_there -> + false = complete_purge(Purge); + _ -> + {true, true} = complete_purge(Purge) + end, + + case Type of + code_gone -> + receive + {'DOWN', M0, process, P0, Reason0} -> + {undef, _} = Reason0 + end, + receive + {'DOWN', M1, process, P1, Reason1} -> + {undef, _} = Reason1 + end, + receive + {'DOWN', M2, process, P2, Reason2} -> + {undef, _} = Reason2 + end; + _ -> + receive + {'DOWN', M0, process, P0, Reason0} -> + completed = Reason0 + end, + receive + {'DOWN', M1, process, P1, Reason1} -> + completed = Reason1 + end, + receive + {'DOWN', M2, process, P2, Reason2} -> + completed = Reason2 + end, + catch erlang:purge_module(my_code_test2), + catch erlang:delete_module(my_code_test2), + catch erlang:purge_module(my_code_test2) + end, + ok. + +wait_until(Fun) -> + ok = wait_until(Fun, 20). + +wait_until(Fun, N) -> + case {Fun(),N} of + {true, _} -> + ok; + {false, 0} -> + timeout; + {false, _} -> + receive after 100 -> ok end, + wait_until(Fun, N-1) + end. + +start_purge(Mod, Type) when is_atom(Mod) + andalso ((Type == true) + orelse (Type == false)) -> + Ref = make_ref(), + erts_code_purger ! {test_purge, Mod, self(), Type, Ref}, + receive + {started, Ref} -> + Ref + end. + +continue_purge(Ref) when is_reference(Ref) -> + erts_code_purger ! {continue, Ref}, + receive + {continued, Ref} -> + ok + end. + +complete_purge(Ref) when is_reference(Ref) -> + erts_code_purger ! {complete, Ref}, + receive + {test_purge, Res, Ref} -> + Res + end. -- cgit v1.2.3 From 24485c421f15b00d0b5c97633d701373b53897a5 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 1 Nov 2016 11:40:48 +0100 Subject: erts: Add notsup error for load_nif/2 from hipe code --- erts/emulator/test/nif_SUITE.erl | 18 ++++++++++++++++++ erts/emulator/test/nif_SUITE_data/hipe_compiled.erl | 6 ++++++ 2 files changed, 24 insertions(+) create mode 100644 erts/emulator/test/nif_SUITE_data/hipe_compiled.erl (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 306f2091a1..3a76ee6aee 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -30,6 +30,7 @@ init_per_testcase/2, end_per_testcase/2, basic/1, reload_error/1, upgrade/1, heap_frag/1, t_on_load/1, + hipe/1, types/1, many_args/1, binaries/1, get_string/1, get_atom/1, maps/1, api_macros/1, @@ -70,6 +71,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [basic, reload_error, upgrade, heap_frag, types, many_args, t_on_load, + hipe, binaries, get_string, get_atom, maps, api_macros, from_array, iolist_as_binary, resource, resource_binary, resource_takeover, threading, send, send2, send3, @@ -88,6 +90,11 @@ all() -> init_per_testcase(t_on_load, Config) -> ets:new(nif_SUITE, [named_table]), Config; +init_per_testcase(hipe, Config) -> + case erlang:system_info(hipe_architecture) of + undefined -> {skip, "HiPE is disabled"}; + _ -> Config + end; init_per_testcase(_Case, Config) -> Config. @@ -411,6 +418,17 @@ t_on_load(Config) when is_list(Config) -> verify_tmpmem(TmpMem), ok. +hipe(Config) when is_list(Config) -> + Data = proplists:get_value(data_dir, Config), + Priv = proplists:get_value(priv_dir, Config), + Src = filename:join(Data, "hipe_compiled"), + {ok,hipe_compiled} = c:c(Src, [{outdir,Priv},native]), + true = code:is_module_native(hipe_compiled), + {error, {notsup,_}} = hipe_compiled:try_load_nif(), + true = code:delete(hipe_compiled), + false = code:purge(hipe_compiled), + ok. + %% Test NIF building heap fragments heap_frag(Config) when is_list(Config) -> diff --git a/erts/emulator/test/nif_SUITE_data/hipe_compiled.erl b/erts/emulator/test/nif_SUITE_data/hipe_compiled.erl new file mode 100644 index 0000000000..84ddbc8d63 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/hipe_compiled.erl @@ -0,0 +1,6 @@ +-module(hipe_compiled). + +-export([try_load_nif/0]). + +try_load_nif() -> + erlang:load_nif("doesn't matter", 0). -- cgit v1.2.3 From 9d751cedd2d24ca476b12052fcc15215c0a384be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 2 Nov 2016 16:48:30 +0100 Subject: erts: Use cmd on windows for port_SUITE --- erts/emulator/test/port_SUITE.erl | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index 4323849465..d4e77d634a 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -976,21 +976,21 @@ try_bad_env(Env) -> %% Test that we can handle a very very large environment gracefully. huge_env(Config) when is_list(Config) -> ct:timetrap({minutes, 2}), - Vars = case os:type() of - {win32,_} -> 500; - _ -> - %% We create a huge environment, - %% 20000 variables is about 25MB - %% which seems to be the limit on Linux. - 20000 - end, + {Vars, Cmd} = case os:type() of + {win32,_} -> {500, "cmd /q /c ls"}; + _ -> + %% We create a huge environment, + %% 20000 variables is about 25MB + %% which seems to be the limit on Linux. + {20000, "ls"} + end, Env = [{[$a + I div (25*25*25*25) rem 25, $a + I div (25*25*25) rem 25, $a + I div (25*25) rem 25, $a+I div 25 rem 25, $a+I rem 25], lists:duplicate(100,$a+I rem 25)} || I <- lists:seq(1,Vars)], - try erlang:open_port({spawn,"ls"},[exit_status, {env, Env}]) of + try erlang:open_port({spawn,Cmd},[exit_status, {env, Env}]) of P -> receive {P, {exit_status,N}} = M -> @@ -1009,7 +1009,10 @@ huge_env(Config) when is_list(Config) -> %% Test to spawn program with command payload buffer %% just around pipe capacity (9f779819f6bda734c5953468f7798) pipe_limit_env(Config) when is_list(Config) -> - Cmd = "true", + Cmd = case os:type() of + {win32,_} -> "cmd /q /c true"; + _ -> "true" + end, CmdSize = command_payload_size(Cmd), Limits = [4096, 16384, 65536], % Try a couple of common pipe buffer sizes @@ -1026,7 +1029,7 @@ pipe_limit_env_do(Bytes, Cmd, CmdSize) -> try erlang:open_port({spawn,Cmd},[exit_status, {env, Env}]) of P -> receive - {P, {exit_status,N}} = M -> + {P, {exit_status,N}} -> %% Bug caused exit_status 150 (EINVAL+128) 0 = N end -- cgit v1.2.3 From 160a28a0912cf87e971ddcbfdb6f76d64581fe44 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 21 Nov 2016 19:26:02 +0100 Subject: erts: Mend broken checks in nif_SUITE Macro CHECK did not fail the test case just some nice logging that no one saw. One ignored failure fixed; a delayed unload after purge due to live resource with dtor. --- erts/emulator/test/nif_SUITE.erl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 3a76ee6aee..37d6e68868 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -21,7 +21,7 @@ -module(nif_SUITE). %%-define(line_trace,true). --define(CHECK(Exp,Got), check(Exp,Got,?LINE)). +-define(CHECK(Exp,Got), Exp = check(Exp,Got,?LINE)). %%-define(CHECK(Exp,Got), Exp = Got). -include_lib("common_test/include/ct.hrl"). @@ -932,7 +932,7 @@ resource_takeover(Config) when is_list(Config) -> ]), ?CHECK([{upgrade,2,1,201}], nif_mod_call_history()), true = erlang:purge_module(nif_mod), - ?CHECK([{unload,1,1,106}], nif_mod_call_history()), + ?CHECK([], nif_mod_call_history()), % BGX2 keeping lib loaded BinA2 = read_resource(0,A2), ok = forget_resource(A2), @@ -945,8 +945,8 @@ resource_takeover(Config) when is_list(Config) -> ?CHECK([], nif_mod_call_history()), % no dtor ok = forget_resource(BGX2), % calling dtor in orphan library v1 still loaded - ?CHECK([{{resource_dtor_B_v1,BinBGX2},1,6,106}], nif_mod_call_history()), - % How to test that lib v1 is closed here? + ?CHECK([{{resource_dtor_B_v1,BinBGX2},1,6,106}, {unload,1,7,107}], + nif_mod_call_history()), ok = forget_resource(NGX2), ?CHECK([], nif_mod_call_history()), % no dtor @@ -1900,7 +1900,8 @@ check(Exp,Got,Line) -> case Got of Exp -> Exp; _ -> - io:format("CHECK at ~p: Expected ~p but got ~p\n",[Line,Exp,Got]), + io:format("CHECK at line ~p\nExpected: ~p\nGot : ~p\n", + [Line,Exp,Got]), Got end. -- cgit v1.2.3 From 491cd4c0c0a534ab89c3ebb4c413301c91c7167d Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 22 Nov 2016 14:37:31 +0100 Subject: erts: Add env variable ERL_CRASH_DUMP_BYTES to limit crash dump size --- erts/emulator/test/bif_SUITE.erl | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl index d31399e4af..b8d89126fe 100644 --- a/erts/emulator/test/bif_SUITE.erl +++ b/erts/emulator/test/bif_SUITE.erl @@ -31,6 +31,7 @@ t_list_to_existing_atom/1,os_env/1,otp_7526/1, binary_to_atom/1,binary_to_existing_atom/1, atom_to_binary/1,min_max/1, erlang_halt/1, + erl_crash_dump_bytes/1, is_builtin/1]). suite() -> @@ -43,6 +44,7 @@ all() -> t_list_to_existing_atom, os_env, otp_7526, display, atom_to_binary, binary_to_atom, binary_to_existing_atom, + erl_crash_dump_bytes, min_max, erlang_halt, is_builtin]. %% Uses erlang:display to test that erts_printf does not do deep recursion @@ -664,7 +666,7 @@ erlang_halt(Config) when is_list(Config) -> [available_internal_state, true]), {badrpc,nodedown} = rpc:call(N4, erts_debug, set_internal_state, [broken_halt, "Validate correct crash dump"]), - ok = wait_until_stable_size(CrashDump,-1), + {ok,_} = wait_until_stable_size(CrashDump,-1), {ok, Bin} = file:read_file(CrashDump), case {string:str(binary_to_list(Bin),"\n=end\n"), string:str(binary_to_list(Bin),"\r\n=end\r\n")} of @@ -681,11 +683,34 @@ wait_until_stable_size(File,PrevSz) -> wait_until_stable_size(File,PrevSz-1); {ok,#file_info{size = PrevSz }} when PrevSz /= -1 -> io:format("Crashdump file size was: ~p (~s)~n",[PrevSz,File]), - ok; + {ok,PrevSz}; {ok,#file_info{size = NewSz }} -> wait_until_stable_size(File,NewSz) end. +% Test erlang:halt with ERL_CRASH_DUMP_BYTES +erl_crash_dump_bytes(Config) when is_list(Config) -> + Bytes = 1000, + CrashDump = do_limited_crash_dump(Config, Bytes), + {ok,ActualBytes} = wait_until_stable_size(CrashDump,-1), + true = ActualBytes < (Bytes + 100), + + NoDump = do_limited_crash_dump(Config,0), + {error,enoent} = wait_until_stable_size(NoDump,-8), + ok. + +do_limited_crash_dump(Config, Bytes) -> + H = hostname(), + {ok,N} = slave:start(H, halt_node), + BytesStr = integer_to_list(Bytes), + CrashDump = filename:join(proplists:get_value(priv_dir,Config), + "erl_crash." ++ BytesStr ++ ".dump"), + true = rpc:call(N, os, putenv, ["ERL_CRASH_DUMP",CrashDump]), + true = rpc:call(N, os, putenv, ["ERL_CRASH_DUMP_BYTES",BytesStr]), + {badrpc,nodedown} = rpc:call(N, erlang, halt, ["Testing ERL_CRASH_DUMP_BYTES"]), + CrashDump. + + is_builtin(_Config) -> Exp0 = [{M,F,A} || {M,_} <- code:all_loaded(), {F,A} <- M:module_info(exports)], -- cgit v1.2.3 From 3d5f679fdb59988369b198776d5e3930b594941a Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 18 Nov 2016 21:43:42 +0100 Subject: erts: Add testing of old nif API --- erts/emulator/test/nif_SUITE.erl | 25 +- erts/emulator/test/nif_SUITE_data/Makefile.src | 5 +- .../test/nif_SUITE_data/nif_api_2_4/README | 6 + .../test/nif_SUITE_data/nif_api_2_4/erl_drv_nif.h | 48 ++ .../test/nif_SUITE_data/nif_api_2_4/erl_nif.h | 237 ++++++++++ .../nif_SUITE_data/nif_api_2_4/erl_nif_api_funcs.h | 503 +++++++++++++++++++++ erts/emulator/test/nif_SUITE_data/nif_mod.1.2_4.c | 4 + erts/emulator/test/nif_SUITE_data/nif_mod.2.2_4.c | 4 + erts/emulator/test/nif_SUITE_data/nif_mod.3.2_4.c | 4 + erts/emulator/test/nif_SUITE_data/nif_mod.c | 9 + erts/emulator/test/nif_SUITE_data/nif_mod.erl | 29 +- 11 files changed, 864 insertions(+), 10 deletions(-) create mode 100644 erts/emulator/test/nif_SUITE_data/nif_api_2_4/README create mode 100644 erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_drv_nif.h create mode 100644 erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif.h create mode 100644 erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif_api_funcs.h create mode 100644 erts/emulator/test/nif_SUITE_data/nif_mod.1.2_4.c create mode 100644 erts/emulator/test/nif_SUITE_data/nif_mod.2.2_4.c create mode 100644 erts/emulator/test/nif_SUITE_data/nif_mod.3.2_4.c (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 37d6e68868..99213a6888 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -155,7 +155,13 @@ reload_error(Config) when is_list(Config) -> ok. %% Test upgrade callback in nif lib -upgrade(Config) when is_list(Config) -> +upgrade(Config) when is_list(Config) -> + [begin io:format("Do test for API version \"~p\"", [API]), + upgrade_do([{nif_api_version,API}|Config]) + end + || API <- ["", ".2_4"]]. + +upgrade_do(Config) -> TmpMem = tmpmem(), ensure_lib_loaded(Config), @@ -295,6 +301,12 @@ upgrade(Config) when is_list(Config) -> %% Test loading/upgrade in on_load t_on_load(Config) when is_list(Config) -> + [begin io:format("Do test for API version \"~p\"", [API]), + t_on_load_do([{nif_api_version,API}|Config]) + end + || API <- ["", ".2_4"]]. + +t_on_load_do(Config) -> TmpMem = tmpmem(), ensure_lib_loaded(Config), @@ -306,6 +318,8 @@ t_on_load(Config) when is_list(Config) -> %% Use ETS to tell nif_mod:on_load what to do ets:insert(nif_SUITE, {data_dir, Data}), ets:insert(nif_SUITE, {lib_version, 1}), + API = proplists:get_value(nif_api_version, Config, ""), + ets:insert(nif_SUITE, {nif_api_version, API}), {module,nif_mod} = code:load_binary(nif_mod,File,Bin), hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()), [{load,1,1,101},{get_priv_data_ptr,1,2,102}] = nif_mod_call_history(), @@ -848,6 +862,12 @@ resource_binary_do() -> %% Test resource takeover by module upgrade resource_takeover(Config) when is_list(Config) -> + [begin io:format("Do test for API version \"~p\"", [API]), + resource_takeover_do([{nif_api_version,API}|Config]) + end + || API <- ["", ".2_4"]]. + +resource_takeover_do(Config) -> TmpMem = tmpmem(), ensure_lib_loaded(Config), @@ -1169,6 +1189,9 @@ resource_takeover(Config) when is_list(Config) -> ok = forget_resource(AN7), [] = nif_mod_call_history(), + true = erlang:delete_module(nif_mod), + true = erlang:purge_module(nif_mod), + true = lists:member(?MODULE, erlang:system_info(taints)), true = lists:member(nif_mod, erlang:system_info(taints)), verify_tmpmem(TmpMem), diff --git a/erts/emulator/test/nif_SUITE_data/Makefile.src b/erts/emulator/test/nif_SUITE_data/Makefile.src index fbb8978771..cbe843b120 100644 --- a/erts/emulator/test/nif_SUITE_data/Makefile.src +++ b/erts/emulator/test/nif_SUITE_data/Makefile.src @@ -2,7 +2,10 @@ NIF_LIBS = nif_SUITE.1@dll@ \ nif_mod.1@dll@ \ nif_mod.2@dll@ \ - nif_mod.3@dll@ + nif_mod.3@dll@ \ + nif_mod.1.2_4@dll@ \ + nif_mod.2.2_4@dll@ \ + nif_mod.3.2_4@dll@ all: $(NIF_LIBS) basic@dll@ rwlock@dll@ tsd@dll@ echo_drv@dll@ diff --git a/erts/emulator/test/nif_SUITE_data/nif_api_2_4/README b/erts/emulator/test/nif_SUITE_data/nif_api_2_4/README new file mode 100644 index 0000000000..7abd0319a6 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_api_2_4/README @@ -0,0 +1,6 @@ +These are old genuine header files +checked out from tag OTP_R16B 05f11890bdfec4bfc3a78e191 + +I choose this API version (2.4) to test, as it's before +the addition of 'options' in ErlNifEntry and 'flags' in ErlNifFunc +and without include of generated erl_native_features_config.h. diff --git a/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_drv_nif.h b/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_drv_nif.h new file mode 100644 index 0000000000..ea013a49a3 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_drv_nif.h @@ -0,0 +1,48 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2010. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +/* + * Common structures for both erl_driver.h and erl_nif.h + */ + +#ifndef __ERL_DRV_NIF_H__ +#define __ERL_DRV_NIF_H__ + +typedef struct { + int driver_major_version; + int driver_minor_version; + char *erts_version; + char *otp_release; + int thread_support; + int smp_support; + int async_threads; + int scheduler_threads; + int nif_major_version; + int nif_minor_version; +} ErlDrvSysInfo; + +typedef struct { + int suggested_stack_size; +} ErlDrvThreadOpts; + +#endif /* __ERL_DRV_NIF_H__ */ + + + + diff --git a/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif.h b/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif.h new file mode 100644 index 0000000000..8006741a63 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif.h @@ -0,0 +1,237 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2009-2013. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +/* Include file for writers of Native Implemented Functions. +*/ + +#ifndef __ERL_NIF_H__ +#define __ERL_NIF_H__ + + +#include "erl_drv_nif.h" + +/* Version history: +** 0.1: R13B03 +** 1.0: R13B04 +** 2.0: R14A +** 2.1: R14B02 "vm_variant" +** 2.2: R14B03 enif_is_exception +** 2.3: R15 enif_make_reverse_list, enif_is_number +** 2.4: R16 enif_consume_timeslice +*/ +#define ERL_NIF_MAJOR_VERSION 2 +#define ERL_NIF_MINOR_VERSION 4 + +#include + +#ifdef SIZEOF_CHAR +# define SIZEOF_CHAR_SAVED__ SIZEOF_CHAR +# undef SIZEOF_CHAR +#endif +#ifdef SIZEOF_SHORT +# define SIZEOF_SHORT_SAVED__ SIZEOF_SHORT +# undef SIZEOF_SHORT +#endif +#ifdef SIZEOF_INT +# define SIZEOF_INT_SAVED__ SIZEOF_INT +# undef SIZEOF_INT +#endif +#ifdef SIZEOF_LONG +# define SIZEOF_LONG_SAVED__ SIZEOF_LONG +# undef SIZEOF_LONG +#endif +#ifdef SIZEOF_LONG_LONG +# define SIZEOF_LONG_LONG_SAVED__ SIZEOF_LONG_LONG +# undef SIZEOF_LONG_LONG +#endif +#ifdef HALFWORD_HEAP_EMULATOR +# define HALFWORD_HEAP_EMULATOR_SAVED__ HALFWORD_HEAP_EMULATOR +# undef HALFWORD_HEAP_EMULATOR +#endif +#include "erl_int_sizes_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) +typedef unsigned __int64 ErlNifUInt64; +typedef __int64 ErlNifSInt64; +#elif SIZEOF_LONG == 8 +typedef unsigned long ErlNifUInt64; +typedef long ErlNifSInt64; +#elif SIZEOF_LONG_LONG == 8 +typedef unsigned long long ErlNifUInt64; +typedef long long ErlNifSInt64; +#else +#error No 64-bit integer type +#endif + +#ifdef HALFWORD_HEAP_EMULATOR +# define ERL_NIF_VM_VARIANT "beam.halfword" +typedef unsigned int ERL_NIF_TERM; +#else +# define ERL_NIF_VM_VARIANT "beam.vanilla" +# if SIZEOF_LONG == SIZEOF_VOID_P +typedef unsigned long ERL_NIF_TERM; +# elif SIZEOF_LONG_LONG == SIZEOF_VOID_P +typedef unsigned long long ERL_NIF_TERM; +# endif +#endif + +struct enif_environment_t; +typedef struct enif_environment_t ErlNifEnv; + +typedef struct +{ + const char* name; + unsigned arity; + ERL_NIF_TERM (*fptr)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +}ErlNifFunc; + +typedef struct enif_entry_t +{ + int major; + int minor; + const char* name; + int num_of_funcs; + ErlNifFunc* funcs; + int (*load) (ErlNifEnv*, void** priv_data, ERL_NIF_TERM load_info); + int (*reload) (ErlNifEnv*, void** priv_data, ERL_NIF_TERM load_info); + int (*upgrade)(ErlNifEnv*, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info); + void (*unload) (ErlNifEnv*, void* priv_data); + const char* vm_variant; +}ErlNifEntry; + + + +typedef struct +{ + size_t size; + unsigned char* data; + + /* Internals (avert your eyes) */ + ERL_NIF_TERM bin_term; + void* ref_bin; +}ErlNifBinary; + +typedef struct enif_resource_type_t ErlNifResourceType; +typedef void ErlNifResourceDtor(ErlNifEnv*, void*); +typedef enum +{ + ERL_NIF_RT_CREATE = 1, + ERL_NIF_RT_TAKEOVER = 2 +}ErlNifResourceFlags; + +typedef enum +{ + ERL_NIF_LATIN1 = 1 +}ErlNifCharEncoding; + +typedef struct +{ + ERL_NIF_TERM pid; /* internal, may change */ +}ErlNifPid; + +typedef ErlDrvSysInfo ErlNifSysInfo; + +typedef struct ErlDrvTid_ *ErlNifTid; +typedef struct ErlDrvMutex_ ErlNifMutex; +typedef struct ErlDrvCond_ ErlNifCond; +typedef struct ErlDrvRWLock_ ErlNifRWLock; +typedef int ErlNifTSDKey; + +typedef ErlDrvThreadOpts ErlNifThreadOpts; + +#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) +# define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) RET_TYPE (*NAME) ARGS +typedef struct { +# include "erl_nif_api_funcs.h" +} TWinDynNifCallbacks; +extern TWinDynNifCallbacks WinDynNifCallbacks; +# undef ERL_NIF_API_FUNC_DECL +#endif + +#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) && !defined(STATIC_ERLANG_DRIVER) +# define ERL_NIF_API_FUNC_MACRO(NAME) (WinDynNifCallbacks.NAME) +# include "erl_nif_api_funcs.h" +/* note that we have to keep ERL_NIF_API_FUNC_MACRO defined */ + +#else /* non windows or included from emulator itself */ + +# define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) extern RET_TYPE NAME ARGS +# include "erl_nif_api_funcs.h" +# undef ERL_NIF_API_FUNC_DECL +#endif + + +#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) +# define ERL_NIF_INIT_GLOB TWinDynNifCallbacks WinDynNifCallbacks; +# define ERL_NIF_INIT_DECL(MODNAME) __declspec(dllexport) ErlNifEntry* nif_init(TWinDynNifCallbacks* callbacks) +# define ERL_NIF_INIT_BODY memcpy(&WinDynNifCallbacks,callbacks,sizeof(TWinDynNifCallbacks)) +#else +# define ERL_NIF_INIT_GLOB +# define ERL_NIF_INIT_BODY +# define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* nif_init(void) +#endif + + +#ifdef __cplusplus +} +# define ERL_NIF_INIT_PROLOGUE extern "C" { +# define ERL_NIF_INIT_EPILOGUE } +#else +# define ERL_NIF_INIT_PROLOGUE +# define ERL_NIF_INIT_EPILOGUE +#endif + + +#define ERL_NIF_INIT(NAME, FUNCS, LOAD, RELOAD, UPGRADE, UNLOAD) \ +ERL_NIF_INIT_PROLOGUE \ +ERL_NIF_INIT_GLOB \ +ERL_NIF_INIT_DECL(NAME); \ +ERL_NIF_INIT_DECL(NAME) \ +{ \ + static ErlNifEntry entry = \ + { \ + ERL_NIF_MAJOR_VERSION, \ + ERL_NIF_MINOR_VERSION, \ + #NAME, \ + sizeof(FUNCS) / sizeof(*FUNCS), \ + FUNCS, \ + LOAD, RELOAD, UPGRADE, UNLOAD, \ + ERL_NIF_VM_VARIANT \ + }; \ + ERL_NIF_INIT_BODY; \ + return &entry; \ +} \ +ERL_NIF_INIT_EPILOGUE + +#if defined(USE_DYNAMIC_TRACE) && (defined(USE_DTRACE) || defined(USE_SYSTEMTAP)) +#define HAVE_USE_DTRACE 1 +#endif + +#ifdef HAVE_USE_DTRACE +ERL_NIF_TERM erl_nif_user_trace_s1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM erl_nif_user_trace_i4s4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM erl_nif_user_trace_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +#endif + +#endif /* __ERL_NIF_H__ */ + diff --git a/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif_api_funcs.h b/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif_api_funcs.h new file mode 100644 index 0000000000..2f841645e1 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif_api_funcs.h @@ -0,0 +1,503 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2009-2013. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#if !defined(ERL_NIF_API_FUNC_DECL) && !defined(ERL_NIF_API_FUNC_MACRO) +# error This file should not be included directly +#endif + +/* +** WARNING: add new ERL_NIF_API_FUNC_DECL entries at the bottom of the list +** to keep compatibility on Windows!!! +** +** And don't forget to increase ERL_NIF_MINOR_VERSION in erl_nif.h +** when adding functions to the API. +*/ +#ifdef ERL_NIF_API_FUNC_DECL +ERL_NIF_API_FUNC_DECL(void*,enif_priv_data,(ErlNifEnv*)); +ERL_NIF_API_FUNC_DECL(void*,enif_alloc,(size_t size)); +ERL_NIF_API_FUNC_DECL(void,enif_free,(void* ptr)); +ERL_NIF_API_FUNC_DECL(int,enif_is_atom,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_is_binary,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_is_ref,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_inspect_binary,(ErlNifEnv*, ERL_NIF_TERM bin_term, ErlNifBinary* bin)); +ERL_NIF_API_FUNC_DECL(int,enif_alloc_binary,(size_t size, ErlNifBinary* bin)); +ERL_NIF_API_FUNC_DECL(int,enif_realloc_binary,(ErlNifBinary* bin, size_t size)); +ERL_NIF_API_FUNC_DECL(void,enif_release_binary,(ErlNifBinary* bin)); +ERL_NIF_API_FUNC_DECL(int,enif_get_int,(ErlNifEnv*, ERL_NIF_TERM term, int* ip)); +ERL_NIF_API_FUNC_DECL(int,enif_get_ulong,(ErlNifEnv*, ERL_NIF_TERM term, unsigned long* ip)); +ERL_NIF_API_FUNC_DECL(int,enif_get_double,(ErlNifEnv*, ERL_NIF_TERM term, double* dp)); +ERL_NIF_API_FUNC_DECL(int,enif_get_list_cell,(ErlNifEnv* env, ERL_NIF_TERM term, ERL_NIF_TERM* head, ERL_NIF_TERM* tail)); +ERL_NIF_API_FUNC_DECL(int,enif_get_tuple,(ErlNifEnv* env, ERL_NIF_TERM tpl, int* arity, const ERL_NIF_TERM** array)); +ERL_NIF_API_FUNC_DECL(int,enif_is_identical,(ERL_NIF_TERM lhs, ERL_NIF_TERM rhs)); +ERL_NIF_API_FUNC_DECL(int,enif_compare,(ERL_NIF_TERM lhs, ERL_NIF_TERM rhs)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_binary,(ErlNifEnv* env, ErlNifBinary* bin)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_badarg,(ErlNifEnv* env)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_int,(ErlNifEnv* env, int i)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_ulong,(ErlNifEnv* env, unsigned long i)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_double,(ErlNifEnv* env, double d)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_atom,(ErlNifEnv* env, const char* name)); +ERL_NIF_API_FUNC_DECL(int,enif_make_existing_atom,(ErlNifEnv* env, const char* name, ERL_NIF_TERM* atom, ErlNifCharEncoding)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_tuple,(ErlNifEnv* env, unsigned cnt, ...)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_list,(ErlNifEnv* env, unsigned cnt, ...)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_list_cell,(ErlNifEnv* env, ERL_NIF_TERM car, ERL_NIF_TERM cdr)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_string,(ErlNifEnv* env, const char* string, ErlNifCharEncoding)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_ref,(ErlNifEnv* env)); + +ERL_NIF_API_FUNC_DECL(ErlNifMutex*,enif_mutex_create,(char *name)); +ERL_NIF_API_FUNC_DECL(void,enif_mutex_destroy,(ErlNifMutex *mtx)); +ERL_NIF_API_FUNC_DECL(int,enif_mutex_trylock,(ErlNifMutex *mtx)); +ERL_NIF_API_FUNC_DECL(void,enif_mutex_lock,(ErlNifMutex *mtx)); +ERL_NIF_API_FUNC_DECL(void,enif_mutex_unlock,(ErlNifMutex *mtx)); +ERL_NIF_API_FUNC_DECL(ErlNifCond*,enif_cond_create,(char *name)); +ERL_NIF_API_FUNC_DECL(void,enif_cond_destroy,(ErlNifCond *cnd)); +ERL_NIF_API_FUNC_DECL(void,enif_cond_signal,(ErlNifCond *cnd)); +ERL_NIF_API_FUNC_DECL(void,enif_cond_broadcast,(ErlNifCond *cnd)); +ERL_NIF_API_FUNC_DECL(void,enif_cond_wait,(ErlNifCond *cnd, ErlNifMutex *mtx)); +ERL_NIF_API_FUNC_DECL(ErlNifRWLock*,enif_rwlock_create,(char *name)); +ERL_NIF_API_FUNC_DECL(void,enif_rwlock_destroy,(ErlNifRWLock *rwlck)); +ERL_NIF_API_FUNC_DECL(int,enif_rwlock_tryrlock,(ErlNifRWLock *rwlck)); +ERL_NIF_API_FUNC_DECL(void,enif_rwlock_rlock,(ErlNifRWLock *rwlck)); +ERL_NIF_API_FUNC_DECL(void,enif_rwlock_runlock,(ErlNifRWLock *rwlck)); +ERL_NIF_API_FUNC_DECL(int,enif_rwlock_tryrwlock,(ErlNifRWLock *rwlck)); +ERL_NIF_API_FUNC_DECL(void,enif_rwlock_rwlock,(ErlNifRWLock *rwlck)); +ERL_NIF_API_FUNC_DECL(void,enif_rwlock_rwunlock,(ErlNifRWLock *rwlck)); +ERL_NIF_API_FUNC_DECL(int,enif_tsd_key_create,(char *name, ErlNifTSDKey *key)); +ERL_NIF_API_FUNC_DECL(void,enif_tsd_key_destroy,(ErlNifTSDKey key)); +ERL_NIF_API_FUNC_DECL(void,enif_tsd_set,(ErlNifTSDKey key, void *data)); +ERL_NIF_API_FUNC_DECL(void*,enif_tsd_get,(ErlNifTSDKey key)); +ERL_NIF_API_FUNC_DECL(ErlNifThreadOpts*,enif_thread_opts_create,(char *name)); +ERL_NIF_API_FUNC_DECL(void,enif_thread_opts_destroy,(ErlNifThreadOpts *opts)); +ERL_NIF_API_FUNC_DECL(int,enif_thread_create,(char *name,ErlNifTid *tid,void * (*func)(void *),void *args,ErlNifThreadOpts *opts)); +ERL_NIF_API_FUNC_DECL(ErlNifTid,enif_thread_self,(void)); +ERL_NIF_API_FUNC_DECL(int,enif_equal_tids,(ErlNifTid tid1, ErlNifTid tid2)); +ERL_NIF_API_FUNC_DECL(void,enif_thread_exit,(void *resp)); +ERL_NIF_API_FUNC_DECL(int,enif_thread_join,(ErlNifTid, void **respp)); + +ERL_NIF_API_FUNC_DECL(void*,enif_realloc,(void* ptr, size_t size)); +ERL_NIF_API_FUNC_DECL(void,enif_system_info,(ErlNifSysInfo *sip, size_t si_size)); +ERL_NIF_API_FUNC_DECL(int,enif_fprintf,(void/* FILE* */ *filep, const char *format, ...)); +ERL_NIF_API_FUNC_DECL(int,enif_inspect_iolist_as_binary,(ErlNifEnv*, ERL_NIF_TERM term, ErlNifBinary* bin)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_sub_binary,(ErlNifEnv*, ERL_NIF_TERM bin_term, size_t pos, size_t size)); +ERL_NIF_API_FUNC_DECL(int,enif_get_string,(ErlNifEnv*, ERL_NIF_TERM list, char* buf, unsigned len, ErlNifCharEncoding)); +ERL_NIF_API_FUNC_DECL(int,enif_get_atom,(ErlNifEnv*, ERL_NIF_TERM atom, char* buf, unsigned len, ErlNifCharEncoding)); +ERL_NIF_API_FUNC_DECL(int,enif_is_fun,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_is_pid,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_is_port,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_get_uint,(ErlNifEnv*, ERL_NIF_TERM term, unsigned* ip)); +ERL_NIF_API_FUNC_DECL(int,enif_get_long,(ErlNifEnv*, ERL_NIF_TERM term, long* ip)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_uint,(ErlNifEnv*, unsigned i)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_long,(ErlNifEnv*, long i)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_tuple_from_array,(ErlNifEnv*, const ERL_NIF_TERM arr[], unsigned cnt)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_list_from_array,(ErlNifEnv*, const ERL_NIF_TERM arr[], unsigned cnt)); +ERL_NIF_API_FUNC_DECL(int,enif_is_empty_list,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(ErlNifResourceType*,enif_open_resource_type,(ErlNifEnv*, const char* module_str, const char* name_str, void (*dtor)(ErlNifEnv*,void *), ErlNifResourceFlags flags, ErlNifResourceFlags* tried)); +ERL_NIF_API_FUNC_DECL(void*,enif_alloc_resource,(ErlNifResourceType* type, size_t size)); +ERL_NIF_API_FUNC_DECL(void,enif_release_resource,(void* obj)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_resource,(ErlNifEnv*, void* obj)); +ERL_NIF_API_FUNC_DECL(int,enif_get_resource,(ErlNifEnv*, ERL_NIF_TERM term, ErlNifResourceType* type, void** objp)); +ERL_NIF_API_FUNC_DECL(size_t,enif_sizeof_resource,(void* obj)); +ERL_NIF_API_FUNC_DECL(unsigned char*,enif_make_new_binary,(ErlNifEnv*,size_t size,ERL_NIF_TERM* termp)); +ERL_NIF_API_FUNC_DECL(int,enif_is_list,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_is_tuple,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_get_atom_length,(ErlNifEnv*, ERL_NIF_TERM atom, unsigned* len, ErlNifCharEncoding)); +ERL_NIF_API_FUNC_DECL(int,enif_get_list_length,(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM, enif_make_atom_len,(ErlNifEnv* env, const char* name, size_t len)); +ERL_NIF_API_FUNC_DECL(int, enif_make_existing_atom_len,(ErlNifEnv* env, const char* name, size_t len, ERL_NIF_TERM* atom, ErlNifCharEncoding)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_string_len,(ErlNifEnv* env, const char* string, size_t len, ErlNifCharEncoding)); +ERL_NIF_API_FUNC_DECL(ErlNifEnv*,enif_alloc_env,(void)); +ERL_NIF_API_FUNC_DECL(void,enif_free_env,(ErlNifEnv* env)); +ERL_NIF_API_FUNC_DECL(void,enif_clear_env,(ErlNifEnv* env)); +ERL_NIF_API_FUNC_DECL(int,enif_send,(ErlNifEnv* env, const ErlNifPid* to_pid, ErlNifEnv* msg_env, ERL_NIF_TERM msg)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_copy,(ErlNifEnv* dst_env, ERL_NIF_TERM src_term)); +ERL_NIF_API_FUNC_DECL(ErlNifPid*,enif_self,(ErlNifEnv* caller_env, ErlNifPid* pid)); +ERL_NIF_API_FUNC_DECL(int,enif_get_local_pid,(ErlNifEnv* env, ERL_NIF_TERM, ErlNifPid* pid)); +ERL_NIF_API_FUNC_DECL(void,enif_keep_resource,(void* obj)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_resource_binary,(ErlNifEnv*,void* obj,const void* data, size_t size)); +#if SIZEOF_LONG != 8 +ERL_NIF_API_FUNC_DECL(int,enif_get_int64,(ErlNifEnv*, ERL_NIF_TERM term, ErlNifSInt64* ip)); +ERL_NIF_API_FUNC_DECL(int,enif_get_uint64,(ErlNifEnv*, ERL_NIF_TERM term, ErlNifUInt64* ip)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_int64,(ErlNifEnv*, ErlNifSInt64)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_uint64,(ErlNifEnv*, ErlNifUInt64)); +#endif +ERL_NIF_API_FUNC_DECL(int,enif_is_exception,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_make_reverse_list,(ErlNifEnv*, ERL_NIF_TERM term, ERL_NIF_TERM *list)); +ERL_NIF_API_FUNC_DECL(int,enif_is_number,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(void*,enif_dlopen,(const char* lib, void (*err_handler)(void*,const char*), void* err_arg)); +ERL_NIF_API_FUNC_DECL(void*,enif_dlsym,(void* handle, const char* symbol, void (*err_handler)(void*,const char*), void* err_arg)); +ERL_NIF_API_FUNC_DECL(int,enif_consume_timeslice,(ErlNifEnv*, int percent)); + +/* +** Add new entries here to keep compatibility on Windows!!! +*/ +#endif + +/* +** Please keep the ERL_NIF_API_FUNC_MACRO list below in the same order +** as the ERL_NIF_API_FUNC_DECL list above +*/ +#ifdef ERL_NIF_API_FUNC_MACRO +# define enif_priv_data ERL_NIF_API_FUNC_MACRO(enif_priv_data) +# define enif_alloc ERL_NIF_API_FUNC_MACRO(enif_alloc) +# define enif_free ERL_NIF_API_FUNC_MACRO(enif_free) +# define enif_is_atom ERL_NIF_API_FUNC_MACRO(enif_is_atom) +# define enif_is_binary ERL_NIF_API_FUNC_MACRO(enif_is_binary) +# define enif_is_ref ERL_NIF_API_FUNC_MACRO(enif_is_ref) +# define enif_inspect_binary ERL_NIF_API_FUNC_MACRO(enif_inspect_binary) +# define enif_alloc_binary ERL_NIF_API_FUNC_MACRO(enif_alloc_binary) +# define enif_realloc_binary ERL_NIF_API_FUNC_MACRO(enif_realloc_binary) +# define enif_release_binary ERL_NIF_API_FUNC_MACRO(enif_release_binary) +# define enif_get_int ERL_NIF_API_FUNC_MACRO(enif_get_int) +# define enif_get_ulong ERL_NIF_API_FUNC_MACRO(enif_get_ulong) +# define enif_get_double ERL_NIF_API_FUNC_MACRO(enif_get_double) +# define enif_get_tuple ERL_NIF_API_FUNC_MACRO(enif_get_tuple) +# define enif_get_list_cell ERL_NIF_API_FUNC_MACRO(enif_get_list_cell) +# define enif_is_identical ERL_NIF_API_FUNC_MACRO(enif_is_identical) +# define enif_compare ERL_NIF_API_FUNC_MACRO(enif_compare) + +# define enif_make_binary ERL_NIF_API_FUNC_MACRO(enif_make_binary) +# define enif_make_badarg ERL_NIF_API_FUNC_MACRO(enif_make_badarg) +# define enif_make_int ERL_NIF_API_FUNC_MACRO(enif_make_int) +# define enif_make_ulong ERL_NIF_API_FUNC_MACRO(enif_make_ulong) +# define enif_make_double ERL_NIF_API_FUNC_MACRO(enif_make_double) +# define enif_make_atom ERL_NIF_API_FUNC_MACRO(enif_make_atom) +# define enif_make_existing_atom ERL_NIF_API_FUNC_MACRO(enif_make_existing_atom) +# define enif_make_tuple ERL_NIF_API_FUNC_MACRO(enif_make_tuple) +# define enif_make_list ERL_NIF_API_FUNC_MACRO(enif_make_list) +# define enif_make_list_cell ERL_NIF_API_FUNC_MACRO(enif_make_list_cell) +# define enif_make_string ERL_NIF_API_FUNC_MACRO(enif_make_string) +# define enif_make_ref ERL_NIF_API_FUNC_MACRO(enif_make_ref) + +# define enif_mutex_create ERL_NIF_API_FUNC_MACRO(enif_mutex_create) +# define enif_mutex_destroy ERL_NIF_API_FUNC_MACRO(enif_mutex_destroy) +# define enif_mutex_trylock ERL_NIF_API_FUNC_MACRO(enif_mutex_trylock) +# define enif_mutex_lock ERL_NIF_API_FUNC_MACRO(enif_mutex_lock) +# define enif_mutex_unlock ERL_NIF_API_FUNC_MACRO(enif_mutex_unlock) +# define enif_cond_create ERL_NIF_API_FUNC_MACRO(enif_cond_create) +# define enif_cond_destroy ERL_NIF_API_FUNC_MACRO(enif_cond_destroy) +# define enif_cond_signal ERL_NIF_API_FUNC_MACRO(enif_cond_signal) +# define enif_cond_broadcast ERL_NIF_API_FUNC_MACRO(enif_cond_broadcast) +# define enif_cond_wait ERL_NIF_API_FUNC_MACRO(enif_cond_wait) +# define enif_rwlock_create ERL_NIF_API_FUNC_MACRO(enif_rwlock_create) +# define enif_rwlock_destroy ERL_NIF_API_FUNC_MACRO(enif_rwlock_destroy) +# define enif_rwlock_tryrlock ERL_NIF_API_FUNC_MACRO(enif_rwlock_tryrlock) +# define enif_rwlock_rlock ERL_NIF_API_FUNC_MACRO(enif_rwlock_rlock) +# define enif_rwlock_runlock ERL_NIF_API_FUNC_MACRO(enif_rwlock_runlock) +# define enif_rwlock_tryrwlock ERL_NIF_API_FUNC_MACRO(enif_rwlock_tryrwlock) +# define enif_rwlock_rwlock ERL_NIF_API_FUNC_MACRO(enif_rwlock_rwlock) +# define enif_rwlock_rwunlock ERL_NIF_API_FUNC_MACRO(enif_rwlock_rwunlock) +# define enif_tsd_key_create ERL_NIF_API_FUNC_MACRO(enif_tsd_key_create) +# define enif_tsd_key_destroy ERL_NIF_API_FUNC_MACRO(enif_tsd_key_destroy) +# define enif_tsd_set ERL_NIF_API_FUNC_MACRO(enif_tsd_set) +# define enif_tsd_get ERL_NIF_API_FUNC_MACRO(enif_tsd_get) +# define enif_thread_opts_create ERL_NIF_API_FUNC_MACRO(enif_thread_opts_create) +# define enif_thread_opts_destroy ERL_NIF_API_FUNC_MACRO(enif_thread_opts_destroy) +# define enif_thread_create ERL_NIF_API_FUNC_MACRO(enif_thread_create) +# define enif_thread_self ERL_NIF_API_FUNC_MACRO(enif_thread_self) +# define enif_equal_tids ERL_NIF_API_FUNC_MACRO(enif_equal_tids) +# define enif_thread_exit ERL_NIF_API_FUNC_MACRO(enif_thread_exit) +# define enif_thread_join ERL_NIF_API_FUNC_MACRO(enif_thread_join) + +# define enif_realloc ERL_NIF_API_FUNC_MACRO(enif_realloc) +# define enif_system_info ERL_NIF_API_FUNC_MACRO(enif_system_info) +# define enif_fprintf ERL_NIF_API_FUNC_MACRO(enif_fprintf) +# define enif_inspect_iolist_as_binary ERL_NIF_API_FUNC_MACRO(enif_inspect_iolist_as_binary) +# define enif_make_sub_binary ERL_NIF_API_FUNC_MACRO(enif_make_sub_binary) +# define enif_get_string ERL_NIF_API_FUNC_MACRO(enif_get_string) +# define enif_get_atom ERL_NIF_API_FUNC_MACRO(enif_get_atom) +# define enif_is_fun ERL_NIF_API_FUNC_MACRO(enif_is_fun) +# define enif_is_pid ERL_NIF_API_FUNC_MACRO(enif_is_pid) +# define enif_is_port ERL_NIF_API_FUNC_MACRO(enif_is_port) +# define enif_get_uint ERL_NIF_API_FUNC_MACRO(enif_get_uint) +# define enif_get_long ERL_NIF_API_FUNC_MACRO(enif_get_long) +# define enif_make_uint ERL_NIF_API_FUNC_MACRO(enif_make_uint) +# define enif_make_long ERL_NIF_API_FUNC_MACRO(enif_make_long) +# define enif_make_tuple_from_array ERL_NIF_API_FUNC_MACRO(enif_make_tuple_from_array) +# define enif_make_list_from_array ERL_NIF_API_FUNC_MACRO(enif_make_list_from_array) +# define enif_is_empty_list ERL_NIF_API_FUNC_MACRO(enif_is_empty_list) +# define enif_open_resource_type ERL_NIF_API_FUNC_MACRO(enif_open_resource_type) +# define enif_alloc_resource ERL_NIF_API_FUNC_MACRO(enif_alloc_resource) +# define enif_release_resource ERL_NIF_API_FUNC_MACRO(enif_release_resource) +# define enif_make_resource ERL_NIF_API_FUNC_MACRO(enif_make_resource) +# define enif_get_resource ERL_NIF_API_FUNC_MACRO(enif_get_resource) +# define enif_sizeof_resource ERL_NIF_API_FUNC_MACRO(enif_sizeof_resource) +# define enif_make_new_binary ERL_NIF_API_FUNC_MACRO(enif_make_new_binary) +# define enif_is_list ERL_NIF_API_FUNC_MACRO(enif_is_list) +# define enif_is_tuple ERL_NIF_API_FUNC_MACRO(enif_is_tuple) +# define enif_get_atom_length ERL_NIF_API_FUNC_MACRO(enif_get_atom_length) +# define enif_get_list_length ERL_NIF_API_FUNC_MACRO(enif_get_list_length) +# define enif_make_atom_len ERL_NIF_API_FUNC_MACRO(enif_make_atom_len) +# define enif_make_existing_atom_len ERL_NIF_API_FUNC_MACRO(enif_make_existing_atom_len) +# define enif_make_string_len ERL_NIF_API_FUNC_MACRO(enif_make_string_len) +# define enif_alloc_env ERL_NIF_API_FUNC_MACRO(enif_alloc_env) +# define enif_free_env ERL_NIF_API_FUNC_MACRO(enif_free_env) +# define enif_clear_env ERL_NIF_API_FUNC_MACRO(enif_clear_env) +# define enif_send ERL_NIF_API_FUNC_MACRO(enif_send) +# define enif_make_copy ERL_NIF_API_FUNC_MACRO(enif_make_copy) +# define enif_self ERL_NIF_API_FUNC_MACRO(enif_self) +# define enif_get_local_pid ERL_NIF_API_FUNC_MACRO(enif_get_local_pid) +# define enif_keep_resource ERL_NIF_API_FUNC_MACRO(enif_keep_resource) +# define enif_make_resource_binary ERL_NIF_API_FUNC_MACRO(enif_make_resource_binary) +#if SIZEOF_LONG != 8 +# define enif_get_int64 ERL_NIF_API_FUNC_MACRO(enif_get_int64) +# define enif_get_uint64 ERL_NIF_API_FUNC_MACRO(enif_get_uint64) +# define enif_make_int64 ERL_NIF_API_FUNC_MACRO(enif_make_int64) +# define enif_make_uint64 ERL_NIF_API_FUNC_MACRO(enif_make_uint64) +#endif + +# define enif_is_exception ERL_NIF_API_FUNC_MACRO(enif_is_exception) +# define enif_make_reverse_list ERL_NIF_API_FUNC_MACRO(enif_make_reverse_list) +# define enif_is_number ERL_NIF_API_FUNC_MACRO(enif_is_number) +# define enif_dlopen ERL_NIF_API_FUNC_MACRO(enif_dlopen) +# define enif_dlsym ERL_NIF_API_FUNC_MACRO(enif_dlsym) +# define enif_consume_timeslice ERL_NIF_API_FUNC_MACRO(enif_consume_timeslice) + +/* +** Add new entries here +*/ +#endif + + +#if defined(__GNUC__) && !(defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) + +/* Inline functions for compile time type checking of arguments to + variadic functions. +*/ + +# define ERL_NIF_INLINE __inline__ + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple1(ErlNifEnv* env, + ERL_NIF_TERM e1) +{ + return enif_make_tuple(env, 1, e1); +} + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple2(ErlNifEnv* env, + ERL_NIF_TERM e1, + ERL_NIF_TERM e2) +{ + return enif_make_tuple(env, 2, e1, e2); +} + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple3(ErlNifEnv* env, + ERL_NIF_TERM e1, + ERL_NIF_TERM e2, + ERL_NIF_TERM e3) +{ + return enif_make_tuple(env, 3, e1, e2, e3); +} + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple4(ErlNifEnv* env, + ERL_NIF_TERM e1, + ERL_NIF_TERM e2, + ERL_NIF_TERM e3, + ERL_NIF_TERM e4) +{ + return enif_make_tuple(env, 4, e1, e2, e3, e4); +} + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple5(ErlNifEnv* env, + ERL_NIF_TERM e1, + ERL_NIF_TERM e2, + ERL_NIF_TERM e3, + ERL_NIF_TERM e4, + ERL_NIF_TERM e5) +{ + return enif_make_tuple(env, 5, e1, e2, e3, e4, e5); +} + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple6(ErlNifEnv* env, + ERL_NIF_TERM e1, + ERL_NIF_TERM e2, + ERL_NIF_TERM e3, + ERL_NIF_TERM e4, + ERL_NIF_TERM e5, + ERL_NIF_TERM e6) +{ + return enif_make_tuple(env, 6, e1, e2, e3, e4, e5, e6); +} + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple7(ErlNifEnv* env, + ERL_NIF_TERM e1, + ERL_NIF_TERM e2, + ERL_NIF_TERM e3, + ERL_NIF_TERM e4, + ERL_NIF_TERM e5, + ERL_NIF_TERM e6, + ERL_NIF_TERM e7) +{ + return enif_make_tuple(env, 7, e1, e2, e3, e4, e5, e6, e7); +} + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple8(ErlNifEnv* env, + ERL_NIF_TERM e1, + ERL_NIF_TERM e2, + ERL_NIF_TERM e3, + ERL_NIF_TERM e4, + ERL_NIF_TERM e5, + ERL_NIF_TERM e6, + ERL_NIF_TERM e7, + ERL_NIF_TERM e8) +{ + return enif_make_tuple(env, 8, e1, e2, e3, e4, e5, e6, e7, e8); +} + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_tuple9(ErlNifEnv* env, + ERL_NIF_TERM e1, + ERL_NIF_TERM e2, + ERL_NIF_TERM e3, + ERL_NIF_TERM e4, + ERL_NIF_TERM e5, + ERL_NIF_TERM e6, + ERL_NIF_TERM e7, + ERL_NIF_TERM e8, + ERL_NIF_TERM e9) +{ + return enif_make_tuple(env, 9, e1, e2, e3, e4, e5, e6, e7, e8, e9); +} + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list1(ErlNifEnv* env, + ERL_NIF_TERM e1) +{ + return enif_make_list(env, 1, e1); +} + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list2(ErlNifEnv* env, + ERL_NIF_TERM e1, + ERL_NIF_TERM e2) +{ + return enif_make_list(env, 2, e1, e2); +} + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list3(ErlNifEnv* env, + ERL_NIF_TERM e1, + ERL_NIF_TERM e2, + ERL_NIF_TERM e3) +{ + return enif_make_list(env, 3, e1, e2, e3); +} + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list4(ErlNifEnv* env, + ERL_NIF_TERM e1, + ERL_NIF_TERM e2, + ERL_NIF_TERM e3, + ERL_NIF_TERM e4) +{ + return enif_make_list(env, 4, e1, e2, e3, e4); +} + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list5(ErlNifEnv* env, + ERL_NIF_TERM e1, + ERL_NIF_TERM e2, + ERL_NIF_TERM e3, + ERL_NIF_TERM e4, + ERL_NIF_TERM e5) +{ + return enif_make_list(env, 5, e1, e2, e3, e4, e5); +} + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list6(ErlNifEnv* env, + ERL_NIF_TERM e1, + ERL_NIF_TERM e2, + ERL_NIF_TERM e3, + ERL_NIF_TERM e4, + ERL_NIF_TERM e5, + ERL_NIF_TERM e6) +{ + return enif_make_list(env, 6, e1, e2, e3, e4, e5, e6); +} + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list7(ErlNifEnv* env, + ERL_NIF_TERM e1, + ERL_NIF_TERM e2, + ERL_NIF_TERM e3, + ERL_NIF_TERM e4, + ERL_NIF_TERM e5, + ERL_NIF_TERM e6, + ERL_NIF_TERM e7) +{ + return enif_make_list(env, 7, e1, e2, e3, e4, e5, e6, e7); +} + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list8(ErlNifEnv* env, + ERL_NIF_TERM e1, + ERL_NIF_TERM e2, + ERL_NIF_TERM e3, + ERL_NIF_TERM e4, + ERL_NIF_TERM e5, + ERL_NIF_TERM e6, + ERL_NIF_TERM e7, + ERL_NIF_TERM e8) +{ + return enif_make_list(env, 8, e1, e2, e3, e4, e5, e6, e7, e8); +} + +static ERL_NIF_INLINE ERL_NIF_TERM enif_make_list9(ErlNifEnv* env, + ERL_NIF_TERM e1, + ERL_NIF_TERM e2, + ERL_NIF_TERM e3, + ERL_NIF_TERM e4, + ERL_NIF_TERM e5, + ERL_NIF_TERM e6, + ERL_NIF_TERM e7, + ERL_NIF_TERM e8, + ERL_NIF_TERM e9) +{ + return enif_make_list(env, 9, e1, e2, e3, e4, e5, e6, e7, e8, e9); +} + +# undef ERL_NIF_INLINE + +#else /* fallback with macros */ + +#ifndef enif_make_list1 +# define enif_make_list1(ENV,E1) enif_make_list(ENV,1,E1) +# define enif_make_list2(ENV,E1,E2) enif_make_list(ENV,2,E1,E2) +# define enif_make_list3(ENV,E1,E2,E3) enif_make_list(ENV,3,E1,E2,E3) +# define enif_make_list4(ENV,E1,E2,E3,E4) enif_make_list(ENV,4,E1,E2,E3,E4) +# define enif_make_list5(ENV,E1,E2,E3,E4,E5) enif_make_list(ENV,5,E1,E2,E3,E4,E5) +# define enif_make_list6(ENV,E1,E2,E3,E4,E5,E6) enif_make_list(ENV,6,E1,E2,E3,E4,E5,E6) +# define enif_make_list7(ENV,E1,E2,E3,E4,E5,E6,E7) enif_make_list(ENV,7,E1,E2,E3,E4,E5,E6,E7) +# define enif_make_list8(ENV,E1,E2,E3,E4,E5,E6,E7,E8) enif_make_list(ENV,8,E1,E2,E3,E4,E5,E6,E7,E8) +# define enif_make_list9(ENV,E1,E2,E3,E4,E5,E6,E7,E8,E9) enif_make_list(ENV,9,E1,E2,E3,E4,E5,E6,E7,E8,E9) +# define enif_make_tuple1(ENV,E1) enif_make_tuple(ENV,1,E1) +# define enif_make_tuple2(ENV,E1,E2) enif_make_tuple(ENV,2,E1,E2) +# define enif_make_tuple3(ENV,E1,E2,E3) enif_make_tuple(ENV,3,E1,E2,E3) +# define enif_make_tuple4(ENV,E1,E2,E3,E4) enif_make_tuple(ENV,4,E1,E2,E3,E4) +# define enif_make_tuple5(ENV,E1,E2,E3,E4,E5) enif_make_tuple(ENV,5,E1,E2,E3,E4,E5) +# define enif_make_tuple6(ENV,E1,E2,E3,E4,E5,E6) enif_make_tuple(ENV,6,E1,E2,E3,E4,E5,E6) +# define enif_make_tuple7(ENV,E1,E2,E3,E4,E5,E6,E7) enif_make_tuple(ENV,7,E1,E2,E3,E4,E5,E6,E7) +# define enif_make_tuple8(ENV,E1,E2,E3,E4,E5,E6,E7,E8) enif_make_tuple(ENV,8,E1,E2,E3,E4,E5,E6,E7,E8) +# define enif_make_tuple9(ENV,E1,E2,E3,E4,E5,E6,E7,E8,E9) enif_make_tuple(ENV,9,E1,E2,E3,E4,E5,E6,E7,E8,E9) +#endif + +#endif /* __GNUC__ && !WIN32 */ + +#ifndef enif_make_pid + +# define enif_make_pid(ENV, PID) ((const ERL_NIF_TERM)((PID)->pid)) + +#if SIZEOF_LONG == 8 +# define enif_get_int64 enif_get_long +# define enif_get_uint64 enif_get_ulong +# define enif_make_int64 enif_make_long +# define enif_make_uint64 enif_make_ulong +#endif + +#endif + diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.1.2_4.c b/erts/emulator/test/nif_SUITE_data/nif_mod.1.2_4.c new file mode 100644 index 0000000000..6d28dbb8ba --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.1.2_4.c @@ -0,0 +1,4 @@ +#include "nif_api_2_4/erl_nif.h" + +#define NIF_LIB_VER 1 +#include "nif_mod.c" diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.2.2_4.c b/erts/emulator/test/nif_SUITE_data/nif_mod.2.2_4.c new file mode 100644 index 0000000000..628fd42b52 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.2.2_4.c @@ -0,0 +1,4 @@ +#include "nif_api_2_4/erl_nif.h" + +#define NIF_LIB_VER 2 +#include "nif_mod.c" diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.3.2_4.c b/erts/emulator/test/nif_SUITE_data/nif_mod.3.2_4.c new file mode 100644 index 0000000000..bdbe8cf381 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.3.2_4.c @@ -0,0 +1,4 @@ +#include "nif_api_2_4/erl_nif.h" + +#define NIF_LIB_VER 3 +#include "nif_mod.c" diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.c b/erts/emulator/test/nif_SUITE_data/nif_mod.c index 4e94e7901c..98eac821b6 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_mod.c +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.c @@ -237,6 +237,14 @@ static ERL_NIF_TERM lib_version(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg return enif_make_int(env, NIF_LIB_VER); } +static ERL_NIF_TERM nif_api_version(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + /*ADD_CALL("nif_api_version");*/ + return enif_make_tuple2(env, + enif_make_int(env, ERL_NIF_MAJOR_VERSION), + enif_make_int(env, ERL_NIF_MINOR_VERSION)); +} + static ERL_NIF_TERM get_priv_data_ptr(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ADD_CALL("get_priv_data_ptr"); @@ -279,6 +287,7 @@ static ERL_NIF_TERM get_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar static ErlNifFunc nif_funcs[] = { {"lib_version", 0, lib_version}, + {"nif_api_version", 0, nif_api_version}, {"get_priv_data_ptr", 0, get_priv_data_ptr}, {"make_new_resource", 2, make_new_resource}, {"get_resource", 2, get_resource} diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.erl b/erts/emulator/test/nif_SUITE_data/nif_mod.erl index 1fcc33faa4..8019cfcf82 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_mod.erl +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.erl @@ -22,7 +22,7 @@ -include_lib("common_test/include/ct.hrl"). --export([load_nif_lib/2, load_nif_lib/3, start/0, lib_version/0, call_history/0, +-export([load_nif_lib/2, load_nif_lib/3, start/0, lib_version/0, get_priv_data_ptr/0, make_new_resource/2, get_resource/2]). -export([loop/0, upgrade/1]). @@ -35,21 +35,32 @@ on_load() -> [{data_dir, Path}] = ets:lookup(nif_SUITE, data_dir), [{lib_version, Ver}] = ets:lookup(nif_SUITE, lib_version), - erlang:load_nif(filename:join(Path,libname(Ver)), []). + [{nif_api_version, API}] = ets:lookup(nif_SUITE, nif_api_version), + R = erlang:load_nif(filename:join(Path,libname(Ver,API)), []), + check_api_version(R, API). -endif. +check_api_version(Err, _) when Err =/= ok -> Err; +check_api_version(ok, []) -> ok; +check_api_version(ok, [$., MajC, $_ | MinS]) -> + {Maj, Min} = {list_to_integer([MajC]), list_to_integer(MinS)}, + {Maj, Min} = nif_api_version(), + ok. + load_nif_lib(Config, Ver) -> load_nif_lib(Config, Ver, []). load_nif_lib(Config, Ver, LoadInfo) -> Path = proplists:get_value(data_dir, Config), - erlang:load_nif(filename:join(Path,libname(Ver)), LoadInfo). - -libname(no_init) -> libname(3); -libname(Ver) when is_integer(Ver) -> - "nif_mod." ++ integer_to_list(Ver). + API = proplists:get_value(nif_api_version, Config, ""), + R = erlang:load_nif(filename:join(Path,libname(Ver,API)), LoadInfo), + check_api_version(R, API). +libname(no_init,API) -> libname(3,API); +libname(Ver,API) when is_integer(Ver) -> + "nif_mod." ++ integer_to_list(Ver) ++ API. + start() -> spawn_opt(?MODULE,loop,[], [link, monitor]). @@ -72,7 +83,9 @@ upgrade(Pid) -> lib_version() -> % NIF undefined. -call_history() -> ?nif_stub. +nif_api_version() -> %NIF + {undefined,undefined}. + get_priv_data_ptr() -> ?nif_stub. make_new_resource(_,_) -> ?nif_stub. get_resource(_,_) -> ?nif_stub. -- cgit v1.2.3 From bc1128ca7bb6ab06a2f15e94c5c9728fc6ba27a6 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 21 Nov 2016 17:28:15 +0100 Subject: erts: Use test groups to repeat for different APIs --- erts/emulator/test/nif_SUITE.erl | 56 ++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 34 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 99213a6888..7cac3bd8b3 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -26,7 +26,8 @@ -include_lib("common_test/include/ct.hrl"). --export([all/0, suite/0, +-export([all/0, suite/0, groups/0, + init_per_group/2, end_per_group/2, init_per_testcase/2, end_per_testcase/2, basic/1, reload_error/1, upgrade/1, heap_frag/1, t_on_load/1, @@ -53,28 +54,20 @@ -export([many_args_100/100]). - -%% -export([lib_version/0,call_history/0,hold_nif_mod_priv_data/1,nif_mod_call_history/0, -%% list_seq/1,type_test/0,tuple_2_list/1,is_identical/2,compare/2, -%% clone_bin/1,make_sub_bin/3,string_to_bin/2,atom_to_bin/2,macros/1, -%% tuple_2_list_and_tuple/1,iolist_2_bin/1,get_resource_type/1,alloc_resource/2, -%% make_resource/1,get_resource/2,release_resource/1,last_resource_dtor_call/0, suite/0, -%% make_new_resource/2,make_new_resource_binary/1,send_list_seq/2,send_new_blob/2, -%% alloc_msgenv/0,clear_msgenv/1,grow_blob/2,send_blob/2,send_blob_thread/3, -%% join_send_thread/1]). - - -define(nif_stub,nif_stub_error(?LINE)). suite() -> [{ct_hooks,[ts_install_cth]}]. -all() -> - [basic, reload_error, upgrade, heap_frag, types, many_args, - t_on_load, +all() -> + [basic] + ++ + [{group, G} || G <- api_groups()] + ++ + [reload_error, heap_frag, types, many_args, hipe, binaries, get_string, get_atom, maps, api_macros, from_array, iolist_as_binary, resource, resource_binary, - resource_takeover, threading, send, send2, send3, + threading, send, send2, send3, send_threaded, neg, is_checks, get_length, make_atom, make_string,reverse_list_test, otp_9828, @@ -87,6 +80,19 @@ all() -> nif_port_command, nif_snprintf]. +groups() -> + [{G, [], api_repeaters()} || G <- api_groups()]. + +api_groups() -> [api_latest, api_2_4]. + +api_repeaters() -> [upgrade, resource_takeover, t_on_load]. + +init_per_group(api_latest, Config) -> Config; +init_per_group(api_2_4, Config) -> + [{nif_api_version, ".2_4"} | Config]. + +end_per_group(_,_) -> ok. + init_per_testcase(t_on_load, Config) -> ets:new(nif_SUITE, [named_table]), Config; @@ -156,12 +162,6 @@ reload_error(Config) when is_list(Config) -> %% Test upgrade callback in nif lib upgrade(Config) when is_list(Config) -> - [begin io:format("Do test for API version \"~p\"", [API]), - upgrade_do([{nif_api_version,API}|Config]) - end - || API <- ["", ".2_4"]]. - -upgrade_do(Config) -> TmpMem = tmpmem(), ensure_lib_loaded(Config), @@ -301,12 +301,6 @@ upgrade_do(Config) -> %% Test loading/upgrade in on_load t_on_load(Config) when is_list(Config) -> - [begin io:format("Do test for API version \"~p\"", [API]), - t_on_load_do([{nif_api_version,API}|Config]) - end - || API <- ["", ".2_4"]]. - -t_on_load_do(Config) -> TmpMem = tmpmem(), ensure_lib_loaded(Config), @@ -862,12 +856,6 @@ resource_binary_do() -> %% Test resource takeover by module upgrade resource_takeover(Config) when is_list(Config) -> - [begin io:format("Do test for API version \"~p\"", [API]), - resource_takeover_do([{nif_api_version,API}|Config]) - end - || API <- ["", ".2_4"]]. - -resource_takeover_do(Config) -> TmpMem = tmpmem(), ensure_lib_loaded(Config), -- cgit v1.2.3 From daa93a64340ba5e3118c2550416e2f324e049531 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 21 Nov 2016 18:35:23 +0100 Subject: erts: Change nif_SUITE to use binaries for raw pointers --- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 15 +++++++++------ erts/emulator/test/nif_SUITE_data/nif_mod.c | 6 +++++- 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index dc6d8cea76..2c93891852 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -104,21 +104,24 @@ struct binary_resource { static int get_pointer(ErlNifEnv* env, ERL_NIF_TERM term, void** pp) { - ErlNifUInt64 i64; - int r = enif_get_uint64(env, term, &i64); + ErlNifBinary bin; + int r = enif_inspect_binary(env, term, &bin); if (r) { - *pp = (void*)i64; + *pp = *(void**)bin.data; } return r; } static ERL_NIF_TERM make_pointer(ErlNifEnv* env, void* p) { - ErlNifUInt64 i64 = (ErlNifUInt64) p; - return enif_make_uint64(env, i64); + void** bin_data; + ERL_NIF_TERM res; + ADD_CALL("get_priv_data_ptr"); + bin_data = (void**)enif_make_new_binary(env, sizeof(void*), &res); + *bin_data = p; + return res; } - static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { PrivData* data = enif_alloc(sizeof(PrivData)); diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.c b/erts/emulator/test/nif_SUITE_data/nif_mod.c index 98eac821b6..e6106b6036 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_mod.c +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.c @@ -247,8 +247,12 @@ static ERL_NIF_TERM nif_api_version(ErlNifEnv* env, int argc, const ERL_NIF_TERM static ERL_NIF_TERM get_priv_data_ptr(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { + NifModPrivData** bin_data; + ERL_NIF_TERM res; ADD_CALL("get_priv_data_ptr"); - return enif_make_uint64(env, (ErlNifUInt64)priv_data(env)); + bin_data = (NifModPrivData**)enif_make_new_binary(env, sizeof(void*), &res); + *bin_data = priv_data(env); + return res; } static ERL_NIF_TERM make_new_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From 99900a1e23adb08980c32e09846c281b698d8340 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 21 Nov 2016 18:32:57 +0100 Subject: erts: Add tests of nif API 2.0 --- erts/emulator/test/nif_SUITE.erl | 6 +- erts/emulator/test/nif_SUITE_data/Makefile.src | 3 + .../test/nif_SUITE_data/nif_api_2_0/README | 5 + .../test/nif_SUITE_data/nif_api_2_0/erl_drv_nif.h | 48 ++++ .../test/nif_SUITE_data/nif_api_2_0/erl_nif.h | 206 +++++++++++++++++ .../nif_SUITE_data/nif_api_2_0/erl_nif_api_funcs.h | 257 +++++++++++++++++++++ erts/emulator/test/nif_SUITE_data/nif_mod.1.2_0.c | 4 + erts/emulator/test/nif_SUITE_data/nif_mod.2.2_0.c | 4 + erts/emulator/test/nif_SUITE_data/nif_mod.3.2_0.c | 4 + 9 files changed, 535 insertions(+), 2 deletions(-) create mode 100644 erts/emulator/test/nif_SUITE_data/nif_api_2_0/README create mode 100644 erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_drv_nif.h create mode 100644 erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif.h create mode 100644 erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif_api_funcs.h create mode 100644 erts/emulator/test/nif_SUITE_data/nif_mod.1.2_0.c create mode 100644 erts/emulator/test/nif_SUITE_data/nif_mod.2.2_0.c create mode 100644 erts/emulator/test/nif_SUITE_data/nif_mod.3.2_0.c (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 7cac3bd8b3..01a5e84dc9 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -83,13 +83,15 @@ all() -> groups() -> [{G, [], api_repeaters()} || G <- api_groups()]. -api_groups() -> [api_latest, api_2_4]. +api_groups() -> [api_latest, api_2_4, api_2_0]. api_repeaters() -> [upgrade, resource_takeover, t_on_load]. init_per_group(api_latest, Config) -> Config; init_per_group(api_2_4, Config) -> - [{nif_api_version, ".2_4"} | Config]. + [{nif_api_version, ".2_4"} | Config]; +init_per_group(api_2_0, Config) -> + [{nif_api_version, ".2_0"} | Config]. end_per_group(_,_) -> ok. diff --git a/erts/emulator/test/nif_SUITE_data/Makefile.src b/erts/emulator/test/nif_SUITE_data/Makefile.src index cbe843b120..de06026780 100644 --- a/erts/emulator/test/nif_SUITE_data/Makefile.src +++ b/erts/emulator/test/nif_SUITE_data/Makefile.src @@ -3,6 +3,9 @@ NIF_LIBS = nif_SUITE.1@dll@ \ nif_mod.1@dll@ \ nif_mod.2@dll@ \ nif_mod.3@dll@ \ + nif_mod.1.2_0@dll@ \ + nif_mod.2.2_0@dll@ \ + nif_mod.3.2_0@dll@ \ nif_mod.1.2_4@dll@ \ nif_mod.2.2_4@dll@ \ nif_mod.3.2_4@dll@ diff --git a/erts/emulator/test/nif_SUITE_data/nif_api_2_0/README b/erts/emulator/test/nif_SUITE_data/nif_api_2_0/README new file mode 100644 index 0000000000..a6ed36f634 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_api_2_0/README @@ -0,0 +1,5 @@ +These are old genuine header files +checked out from tag OTP_R14A c1e94fa9a6fe4ae717d35. + +I choose this API version (2.0) to test as it's +before the addition of vm_variant in ErlNifEntry. diff --git a/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_drv_nif.h b/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_drv_nif.h new file mode 100644 index 0000000000..ea013a49a3 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_drv_nif.h @@ -0,0 +1,48 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2010. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +/* + * Common structures for both erl_driver.h and erl_nif.h + */ + +#ifndef __ERL_DRV_NIF_H__ +#define __ERL_DRV_NIF_H__ + +typedef struct { + int driver_major_version; + int driver_minor_version; + char *erts_version; + char *otp_release; + int thread_support; + int smp_support; + int async_threads; + int scheduler_threads; + int nif_major_version; + int nif_minor_version; +} ErlDrvSysInfo; + +typedef struct { + int suggested_stack_size; +} ErlDrvThreadOpts; + +#endif /* __ERL_DRV_NIF_H__ */ + + + + diff --git a/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif.h b/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif.h new file mode 100644 index 0000000000..936f03bce1 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif.h @@ -0,0 +1,206 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2009-2010. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +/* Include file for writers of Native Implemented Functions. +*/ + +#ifndef __ERL_NIF_H__ +#define __ERL_NIF_H__ + + +#include "erl_drv_nif.h" + +/* Version history: +** 0.1: R13B03 +** 1.0: R13B04 +** 2.0: R14A +*/ +#define ERL_NIF_MAJOR_VERSION 2 +#define ERL_NIF_MINOR_VERSION 0 + +#include + +#ifdef SIZEOF_CHAR +# define SIZEOF_CHAR_SAVED__ SIZEOF_CHAR +# undef SIZEOF_CHAR +#endif +#ifdef SIZEOF_SHORT +# define SIZEOF_SHORT_SAVED__ SIZEOF_SHORT +# undef SIZEOF_SHORT +#endif +#ifdef SIZEOF_INT +# define SIZEOF_INT_SAVED__ SIZEOF_INT +# undef SIZEOF_INT +#endif +#ifdef SIZEOF_LONG +# define SIZEOF_LONG_SAVED__ SIZEOF_LONG +# undef SIZEOF_LONG +#endif +#ifdef SIZEOF_LONG_LONG +# define SIZEOF_LONG_LONG_SAVED__ SIZEOF_LONG_LONG +# undef SIZEOF_LONG_LONG +#endif +#ifdef HALFWORD_HEAP_EMULATOR +# define HALFWORD_HEAP_EMULATOR_SAVED__ HALFWORD_HEAP_EMULATOR +# undef HALFWORD_HEAP_EMULATOR +#endif +#include "erl_int_sizes_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HALFWORD_HEAP_EMULATOR +typedef unsigned int ERL_NIF_TERM; +#else +typedef unsigned long ERL_NIF_TERM; +#endif + +struct enif_environment_t; +typedef struct enif_environment_t ErlNifEnv; + +typedef struct +{ + const char* name; + unsigned arity; + ERL_NIF_TERM (*fptr)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +}ErlNifFunc; + +typedef struct enif_entry_t +{ + int major; + int minor; + const char* name; + int num_of_funcs; + ErlNifFunc* funcs; + int (*load) (ErlNifEnv*, void** priv_data, ERL_NIF_TERM load_info); + int (*reload) (ErlNifEnv*, void** priv_data, ERL_NIF_TERM load_info); + int (*upgrade)(ErlNifEnv*, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info); + void (*unload) (ErlNifEnv*, void* priv_data); +}ErlNifEntry; + + + +typedef struct +{ + size_t size; + unsigned char* data; + + /* Internals (avert your eyes) */ + ERL_NIF_TERM bin_term; + void* ref_bin; +}ErlNifBinary; + +typedef struct enif_resource_type_t ErlNifResourceType; +typedef void ErlNifResourceDtor(ErlNifEnv*, void*); +typedef enum +{ + ERL_NIF_RT_CREATE = 1, + ERL_NIF_RT_TAKEOVER = 2 +}ErlNifResourceFlags; + +typedef enum +{ + ERL_NIF_LATIN1 = 1 +}ErlNifCharEncoding; + +typedef struct +{ + ERL_NIF_TERM pid; /* internal, may change */ +}ErlNifPid; + +typedef ErlDrvSysInfo ErlNifSysInfo; + +typedef struct ErlDrvTid_ *ErlNifTid; +typedef struct ErlDrvMutex_ ErlNifMutex; +typedef struct ErlDrvCond_ ErlNifCond; +typedef struct ErlDrvRWLock_ ErlNifRWLock; +typedef int ErlNifTSDKey; + +typedef ErlDrvThreadOpts ErlNifThreadOpts; + +#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) +# define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) RET_TYPE (*NAME) ARGS +typedef struct { +# include "erl_nif_api_funcs.h" +} TWinDynNifCallbacks; +extern TWinDynNifCallbacks WinDynNifCallbacks; +# undef ERL_NIF_API_FUNC_DECL +#endif + +#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) && !defined(STATIC_ERLANG_DRIVER) +# define ERL_NIF_API_FUNC_MACRO(NAME) (WinDynNifCallbacks.NAME) +# include "erl_nif_api_funcs.h" +/* note that we have to keep ERL_NIF_API_FUNC_MACRO defined */ + +#else /* non windows or included from emulator itself */ + +# define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) extern RET_TYPE NAME ARGS +# include "erl_nif_api_funcs.h" +# undef ERL_NIF_API_FUNC_DECL +#endif + + +#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) +# define ERL_NIF_INIT_GLOB TWinDynNifCallbacks WinDynNifCallbacks; +# define ERL_NIF_INIT_DECL(MODNAME) __declspec(dllexport) ErlNifEntry* nif_init(TWinDynNifCallbacks* callbacks) +# define ERL_NIF_INIT_BODY memcpy(&WinDynNifCallbacks,callbacks,sizeof(TWinDynNifCallbacks)) +#else +# define ERL_NIF_INIT_GLOB +# define ERL_NIF_INIT_BODY +# if defined(VXWORKS) +# define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* MODNAME ## _init(void) +# else +# define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* nif_init(void) +# endif +#endif + + +#ifdef __cplusplus +} +# define ERL_NIF_INIT_PROLOGUE extern "C" { +# define ERL_NIF_INIT_EPILOGUE } +#else +# define ERL_NIF_INIT_PROLOGUE +# define ERL_NIF_INIT_EPILOGUE +#endif + + +#define ERL_NIF_INIT(NAME, FUNCS, LOAD, RELOAD, UPGRADE, UNLOAD) \ +ERL_NIF_INIT_PROLOGUE \ +ERL_NIF_INIT_GLOB \ +ERL_NIF_INIT_DECL(NAME) \ +{ \ + static ErlNifEntry entry = \ + { \ + ERL_NIF_MAJOR_VERSION, \ + ERL_NIF_MINOR_VERSION, \ + #NAME, \ + sizeof(FUNCS) / sizeof(*FUNCS), \ + FUNCS, \ + LOAD, RELOAD, UPGRADE, UNLOAD \ + }; \ + ERL_NIF_INIT_BODY; \ + return &entry; \ +} \ +ERL_NIF_INIT_EPILOGUE + + +#endif /* __ERL_NIF_H__ */ + diff --git a/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif_api_funcs.h b/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif_api_funcs.h new file mode 100644 index 0000000000..ef4e9580b0 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif_api_funcs.h @@ -0,0 +1,257 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2009-2010. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#if !defined(ERL_NIF_API_FUNC_DECL) && !defined(ERL_NIF_API_FUNC_MACRO) +# error This file should not be included directly +#endif + +#ifdef ERL_NIF_API_FUNC_DECL +ERL_NIF_API_FUNC_DECL(void*,enif_priv_data,(ErlNifEnv*)); +ERL_NIF_API_FUNC_DECL(void*,enif_alloc,(size_t size)); +ERL_NIF_API_FUNC_DECL(void,enif_free,(void* ptr)); +ERL_NIF_API_FUNC_DECL(int,enif_is_atom,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_is_binary,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_is_ref,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_inspect_binary,(ErlNifEnv*, ERL_NIF_TERM bin_term, ErlNifBinary* bin)); +ERL_NIF_API_FUNC_DECL(int,enif_alloc_binary,(size_t size, ErlNifBinary* bin)); +ERL_NIF_API_FUNC_DECL(int,enif_realloc_binary,(ErlNifBinary* bin, size_t size)); +ERL_NIF_API_FUNC_DECL(void,enif_release_binary,(ErlNifBinary* bin)); +ERL_NIF_API_FUNC_DECL(int,enif_get_int,(ErlNifEnv*, ERL_NIF_TERM term, int* ip)); +ERL_NIF_API_FUNC_DECL(int,enif_get_ulong,(ErlNifEnv*, ERL_NIF_TERM term, unsigned long* ip)); +ERL_NIF_API_FUNC_DECL(int,enif_get_double,(ErlNifEnv*, ERL_NIF_TERM term, double* dp)); +ERL_NIF_API_FUNC_DECL(int,enif_get_list_cell,(ErlNifEnv* env, ERL_NIF_TERM term, ERL_NIF_TERM* head, ERL_NIF_TERM* tail)); +ERL_NIF_API_FUNC_DECL(int,enif_get_tuple,(ErlNifEnv* env, ERL_NIF_TERM tpl, int* arity, const ERL_NIF_TERM** array)); +ERL_NIF_API_FUNC_DECL(int,enif_is_identical,(ERL_NIF_TERM lhs, ERL_NIF_TERM rhs)); +ERL_NIF_API_FUNC_DECL(int,enif_compare,(ERL_NIF_TERM lhs, ERL_NIF_TERM rhs)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_binary,(ErlNifEnv* env, ErlNifBinary* bin)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_badarg,(ErlNifEnv* env)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_int,(ErlNifEnv* env, int i)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_ulong,(ErlNifEnv* env, unsigned long i)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_double,(ErlNifEnv* env, double d)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_atom,(ErlNifEnv* env, const char* name)); +ERL_NIF_API_FUNC_DECL(int,enif_make_existing_atom,(ErlNifEnv* env, const char* name, ERL_NIF_TERM* atom, ErlNifCharEncoding)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_tuple,(ErlNifEnv* env, unsigned cnt, ...)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_list,(ErlNifEnv* env, unsigned cnt, ...)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_list_cell,(ErlNifEnv* env, ERL_NIF_TERM car, ERL_NIF_TERM cdr)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_string,(ErlNifEnv* env, const char* string, ErlNifCharEncoding)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_ref,(ErlNifEnv* env)); + +ERL_NIF_API_FUNC_DECL(ErlNifMutex*,enif_mutex_create,(char *name)); +ERL_NIF_API_FUNC_DECL(void,enif_mutex_destroy,(ErlNifMutex *mtx)); +ERL_NIF_API_FUNC_DECL(int,enif_mutex_trylock,(ErlNifMutex *mtx)); +ERL_NIF_API_FUNC_DECL(void,enif_mutex_lock,(ErlNifMutex *mtx)); +ERL_NIF_API_FUNC_DECL(void,enif_mutex_unlock,(ErlNifMutex *mtx)); +ERL_NIF_API_FUNC_DECL(ErlNifCond*,enif_cond_create,(char *name)); +ERL_NIF_API_FUNC_DECL(void,enif_cond_destroy,(ErlNifCond *cnd)); +ERL_NIF_API_FUNC_DECL(void,enif_cond_signal,(ErlNifCond *cnd)); +ERL_NIF_API_FUNC_DECL(void,enif_cond_broadcast,(ErlNifCond *cnd)); +ERL_NIF_API_FUNC_DECL(void,enif_cond_wait,(ErlNifCond *cnd, ErlNifMutex *mtx)); +ERL_NIF_API_FUNC_DECL(ErlNifRWLock*,enif_rwlock_create,(char *name)); +ERL_NIF_API_FUNC_DECL(void,enif_rwlock_destroy,(ErlNifRWLock *rwlck)); +ERL_NIF_API_FUNC_DECL(int,enif_rwlock_tryrlock,(ErlNifRWLock *rwlck)); +ERL_NIF_API_FUNC_DECL(void,enif_rwlock_rlock,(ErlNifRWLock *rwlck)); +ERL_NIF_API_FUNC_DECL(void,enif_rwlock_runlock,(ErlNifRWLock *rwlck)); +ERL_NIF_API_FUNC_DECL(int,enif_rwlock_tryrwlock,(ErlNifRWLock *rwlck)); +ERL_NIF_API_FUNC_DECL(void,enif_rwlock_rwlock,(ErlNifRWLock *rwlck)); +ERL_NIF_API_FUNC_DECL(void,enif_rwlock_rwunlock,(ErlNifRWLock *rwlck)); +ERL_NIF_API_FUNC_DECL(int,enif_tsd_key_create,(char *name, ErlNifTSDKey *key)); +ERL_NIF_API_FUNC_DECL(void,enif_tsd_key_destroy,(ErlNifTSDKey key)); +ERL_NIF_API_FUNC_DECL(void,enif_tsd_set,(ErlNifTSDKey key, void *data)); +ERL_NIF_API_FUNC_DECL(void*,enif_tsd_get,(ErlNifTSDKey key)); +ERL_NIF_API_FUNC_DECL(ErlNifThreadOpts*,enif_thread_opts_create,(char *name)); +ERL_NIF_API_FUNC_DECL(void,enif_thread_opts_destroy,(ErlNifThreadOpts *opts)); +ERL_NIF_API_FUNC_DECL(int,enif_thread_create,(char *name,ErlNifTid *tid,void * (*func)(void *),void *args,ErlNifThreadOpts *opts)); +ERL_NIF_API_FUNC_DECL(ErlNifTid,enif_thread_self,(void)); +ERL_NIF_API_FUNC_DECL(int,enif_equal_tids,(ErlNifTid tid1, ErlNifTid tid2)); +ERL_NIF_API_FUNC_DECL(void,enif_thread_exit,(void *resp)); +ERL_NIF_API_FUNC_DECL(int,enif_thread_join,(ErlNifTid, void **respp)); + +ERL_NIF_API_FUNC_DECL(void*,enif_realloc,(void* ptr, size_t size)); +ERL_NIF_API_FUNC_DECL(void,enif_system_info,(ErlNifSysInfo *sip, size_t si_size)); +ERL_NIF_API_FUNC_DECL(int,enif_fprintf,(void/* FILE* */ *filep, const char *format, ...)); +ERL_NIF_API_FUNC_DECL(int,enif_inspect_iolist_as_binary,(ErlNifEnv*, ERL_NIF_TERM term, ErlNifBinary* bin)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_sub_binary,(ErlNifEnv*, ERL_NIF_TERM bin_term, size_t pos, size_t size)); +ERL_NIF_API_FUNC_DECL(int,enif_get_string,(ErlNifEnv*, ERL_NIF_TERM list, char* buf, unsigned len, ErlNifCharEncoding)); +ERL_NIF_API_FUNC_DECL(int,enif_get_atom,(ErlNifEnv*, ERL_NIF_TERM atom, char* buf, unsigned len, ErlNifCharEncoding)); +ERL_NIF_API_FUNC_DECL(int,enif_is_fun,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_is_pid,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_is_port,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_get_uint,(ErlNifEnv*, ERL_NIF_TERM term, unsigned* ip)); +ERL_NIF_API_FUNC_DECL(int,enif_get_long,(ErlNifEnv*, ERL_NIF_TERM term, long* ip)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_uint,(ErlNifEnv*, unsigned i)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_long,(ErlNifEnv*, long i)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_tuple_from_array,(ErlNifEnv*, const ERL_NIF_TERM arr[], unsigned cnt)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_list_from_array,(ErlNifEnv*, const ERL_NIF_TERM arr[], unsigned cnt)); +ERL_NIF_API_FUNC_DECL(int,enif_is_empty_list,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(ErlNifResourceType*,enif_open_resource_type,(ErlNifEnv*, const char* module_str, const char* name_str, void (*dtor)(ErlNifEnv*,void *), ErlNifResourceFlags flags, ErlNifResourceFlags* tried)); +ERL_NIF_API_FUNC_DECL(void*,enif_alloc_resource,(ErlNifResourceType* type, size_t size)); +ERL_NIF_API_FUNC_DECL(void,enif_release_resource,(void* obj)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_resource,(ErlNifEnv*, void* obj)); +ERL_NIF_API_FUNC_DECL(int,enif_get_resource,(ErlNifEnv*, ERL_NIF_TERM term, ErlNifResourceType* type, void** objp)); +ERL_NIF_API_FUNC_DECL(size_t,enif_sizeof_resource,(void* obj)); +ERL_NIF_API_FUNC_DECL(unsigned char*,enif_make_new_binary,(ErlNifEnv*,size_t size,ERL_NIF_TERM* termp)); +ERL_NIF_API_FUNC_DECL(int,enif_is_list,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_is_tuple,(ErlNifEnv*, ERL_NIF_TERM term)); +ERL_NIF_API_FUNC_DECL(int,enif_get_atom_length,(ErlNifEnv*, ERL_NIF_TERM atom, unsigned* len, ErlNifCharEncoding)); +ERL_NIF_API_FUNC_DECL(int,enif_get_list_length,(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM, enif_make_atom_len,(ErlNifEnv* env, const char* name, size_t len)); +ERL_NIF_API_FUNC_DECL(int, enif_make_existing_atom_len,(ErlNifEnv* env, const char* name, size_t len, ERL_NIF_TERM* atom, ErlNifCharEncoding)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_string_len,(ErlNifEnv* env, const char* string, size_t len, ErlNifCharEncoding)); +ERL_NIF_API_FUNC_DECL(ErlNifEnv*,enif_alloc_env,(void)); +ERL_NIF_API_FUNC_DECL(void,enif_free_env,(ErlNifEnv* env)); +ERL_NIF_API_FUNC_DECL(void,enif_clear_env,(ErlNifEnv* env)); +ERL_NIF_API_FUNC_DECL(int,enif_send,(ErlNifEnv* env, const ErlNifPid* to_pid, ErlNifEnv* msg_env, ERL_NIF_TERM msg)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_copy,(ErlNifEnv* dst_env, ERL_NIF_TERM src_term)); +ERL_NIF_API_FUNC_DECL(ErlNifPid*,enif_self,(ErlNifEnv* caller_env, ErlNifPid* pid)); +ERL_NIF_API_FUNC_DECL(int,enif_get_local_pid,(ErlNifEnv* env, ERL_NIF_TERM, ErlNifPid* pid)); +ERL_NIF_API_FUNC_DECL(void,enif_keep_resource,(void* obj)); +ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_resource_binary,(ErlNifEnv*,void* obj,const void* data, size_t size)); + +/* +** Add last to keep compatibility on Windows!!! +*/ +#endif + +#ifdef ERL_NIF_API_FUNC_MACRO +# define enif_priv_data ERL_NIF_API_FUNC_MACRO(enif_priv_data) +# define enif_alloc ERL_NIF_API_FUNC_MACRO(enif_alloc) +# define enif_free ERL_NIF_API_FUNC_MACRO(enif_free) +# define enif_is_atom ERL_NIF_API_FUNC_MACRO(enif_is_atom) +# define enif_is_binary ERL_NIF_API_FUNC_MACRO(enif_is_binary) +# define enif_is_ref ERL_NIF_API_FUNC_MACRO(enif_is_ref) +# define enif_inspect_binary ERL_NIF_API_FUNC_MACRO(enif_inspect_binary) +# define enif_alloc_binary ERL_NIF_API_FUNC_MACRO(enif_alloc_binary) +# define enif_realloc_binary ERL_NIF_API_FUNC_MACRO(enif_realloc_binary) +# define enif_release_binary ERL_NIF_API_FUNC_MACRO(enif_release_binary) +# define enif_get_int ERL_NIF_API_FUNC_MACRO(enif_get_int) +# define enif_get_ulong ERL_NIF_API_FUNC_MACRO(enif_get_ulong) +# define enif_get_double ERL_NIF_API_FUNC_MACRO(enif_get_double) +# define enif_get_tuple ERL_NIF_API_FUNC_MACRO(enif_get_tuple) +# define enif_get_list_cell ERL_NIF_API_FUNC_MACRO(enif_get_list_cell) +# define enif_is_identical ERL_NIF_API_FUNC_MACRO(enif_is_identical) +# define enif_compare ERL_NIF_API_FUNC_MACRO(enif_compare) + +# define enif_make_binary ERL_NIF_API_FUNC_MACRO(enif_make_binary) +# define enif_make_badarg ERL_NIF_API_FUNC_MACRO(enif_make_badarg) +# define enif_make_int ERL_NIF_API_FUNC_MACRO(enif_make_int) +# define enif_make_ulong ERL_NIF_API_FUNC_MACRO(enif_make_ulong) +# define enif_make_double ERL_NIF_API_FUNC_MACRO(enif_make_double) +# define enif_make_atom ERL_NIF_API_FUNC_MACRO(enif_make_atom) +# define enif_make_existing_atom ERL_NIF_API_FUNC_MACRO(enif_make_existing_atom) +# define enif_make_tuple ERL_NIF_API_FUNC_MACRO(enif_make_tuple) +# define enif_make_list ERL_NIF_API_FUNC_MACRO(enif_make_list) +# define enif_make_list_cell ERL_NIF_API_FUNC_MACRO(enif_make_list_cell) +# define enif_make_string ERL_NIF_API_FUNC_MACRO(enif_make_string) +# define enif_make_ref ERL_NIF_API_FUNC_MACRO(enif_make_ref) + +# define enif_mutex_create ERL_NIF_API_FUNC_MACRO(enif_mutex_create) +# define enif_mutex_destroy ERL_NIF_API_FUNC_MACRO(enif_mutex_destroy) +# define enif_mutex_trylock ERL_NIF_API_FUNC_MACRO(enif_mutex_trylock) +# define enif_mutex_lock ERL_NIF_API_FUNC_MACRO(enif_mutex_lock) +# define enif_mutex_unlock ERL_NIF_API_FUNC_MACRO(enif_mutex_unlock) +# define enif_cond_create ERL_NIF_API_FUNC_MACRO(enif_cond_create) +# define enif_cond_destroy ERL_NIF_API_FUNC_MACRO(enif_cond_destroy) +# define enif_cond_signal ERL_NIF_API_FUNC_MACRO(enif_cond_signal) +# define enif_cond_broadcast ERL_NIF_API_FUNC_MACRO(enif_cond_broadcast) +# define enif_cond_wait ERL_NIF_API_FUNC_MACRO(enif_cond_wait) +# define enif_rwlock_create ERL_NIF_API_FUNC_MACRO(enif_rwlock_create) +# define enif_rwlock_destroy ERL_NIF_API_FUNC_MACRO(enif_rwlock_destroy) +# define enif_rwlock_tryrlock ERL_NIF_API_FUNC_MACRO(enif_rwlock_tryrlock) +# define enif_rwlock_rlock ERL_NIF_API_FUNC_MACRO(enif_rwlock_rlock) +# define enif_rwlock_runlock ERL_NIF_API_FUNC_MACRO(enif_rwlock_runlock) +# define enif_rwlock_tryrwlock ERL_NIF_API_FUNC_MACRO(enif_rwlock_tryrwlock) +# define enif_rwlock_rwlock ERL_NIF_API_FUNC_MACRO(enif_rwlock_rwlock) +# define enif_rwlock_rwunlock ERL_NIF_API_FUNC_MACRO(enif_rwlock_rwunlock) +# define enif_tsd_key_create ERL_NIF_API_FUNC_MACRO(enif_tsd_key_create) +# define enif_tsd_key_destroy ERL_NIF_API_FUNC_MACRO(enif_tsd_key_destroy) +# define enif_tsd_set ERL_NIF_API_FUNC_MACRO(enif_tsd_set) +# define enif_tsd_get ERL_NIF_API_FUNC_MACRO(enif_tsd_get) +# define enif_thread_opts_create ERL_NIF_API_FUNC_MACRO(enif_thread_opts_create) +# define enif_thread_opts_destroy ERL_NIF_API_FUNC_MACRO(enif_thread_opts_destroy) +# define enif_thread_create ERL_NIF_API_FUNC_MACRO(enif_thread_create) +# define enif_thread_self ERL_NIF_API_FUNC_MACRO(enif_thread_self) +# define enif_equal_tids ERL_NIF_API_FUNC_MACRO(enif_equal_tids) +# define enif_thread_exit ERL_NIF_API_FUNC_MACRO(enif_thread_exit) +# define enif_thread_join ERL_NIF_API_FUNC_MACRO(enif_thread_join) + +# define enif_realloc ERL_NIF_API_FUNC_MACRO(enif_realloc) +# define enif_system_info ERL_NIF_API_FUNC_MACRO(enif_system_info) +# define enif_fprintf ERL_NIF_API_FUNC_MACRO(enif_fprintf) +# define enif_inspect_iolist_as_binary ERL_NIF_API_FUNC_MACRO(enif_inspect_iolist_as_binary) +# define enif_make_sub_binary ERL_NIF_API_FUNC_MACRO(enif_make_sub_binary) +# define enif_get_string ERL_NIF_API_FUNC_MACRO(enif_get_string) +# define enif_get_atom ERL_NIF_API_FUNC_MACRO(enif_get_atom) +# define enif_is_fun ERL_NIF_API_FUNC_MACRO(enif_is_fun) +# define enif_is_pid ERL_NIF_API_FUNC_MACRO(enif_is_pid) +# define enif_is_port ERL_NIF_API_FUNC_MACRO(enif_is_port) +# define enif_get_uint ERL_NIF_API_FUNC_MACRO(enif_get_uint) +# define enif_get_long ERL_NIF_API_FUNC_MACRO(enif_get_long) +# define enif_make_uint ERL_NIF_API_FUNC_MACRO(enif_make_uint) +# define enif_make_long ERL_NIF_API_FUNC_MACRO(enif_make_long) +# define enif_make_tuple_from_array ERL_NIF_API_FUNC_MACRO(enif_make_tuple_from_array) +# define enif_make_list_from_array ERL_NIF_API_FUNC_MACRO(enif_make_list_from_array) +# define enif_is_empty_list ERL_NIF_API_FUNC_MACRO(enif_is_empty_list) +# define enif_open_resource_type ERL_NIF_API_FUNC_MACRO(enif_open_resource_type) +# define enif_alloc_resource ERL_NIF_API_FUNC_MACRO(enif_alloc_resource) +# define enif_release_resource ERL_NIF_API_FUNC_MACRO(enif_release_resource) +# define enif_make_resource ERL_NIF_API_FUNC_MACRO(enif_make_resource) +# define enif_get_resource ERL_NIF_API_FUNC_MACRO(enif_get_resource) +# define enif_sizeof_resource ERL_NIF_API_FUNC_MACRO(enif_sizeof_resource) +# define enif_make_new_binary ERL_NIF_API_FUNC_MACRO(enif_make_new_binary) +# define enif_is_list ERL_NIF_API_FUNC_MACRO(enif_is_list) +# define enif_is_tuple ERL_NIF_API_FUNC_MACRO(enif_is_tuple) +# define enif_get_atom_length ERL_NIF_API_FUNC_MACRO(enif_get_atom_length) +# define enif_get_list_length ERL_NIF_API_FUNC_MACRO(enif_get_list_length) +# define enif_make_atom_len ERL_NIF_API_FUNC_MACRO(enif_make_atom_len) +# define enif_make_existing_atom_len ERL_NIF_API_FUNC_MACRO(enif_make_existing_atom_len) +# define enif_make_string_len ERL_NIF_API_FUNC_MACRO(enif_make_string_len) +# define enif_alloc_env ERL_NIF_API_FUNC_MACRO(enif_alloc_env) +# define enif_free_env ERL_NIF_API_FUNC_MACRO(enif_free_env) +# define enif_clear_env ERL_NIF_API_FUNC_MACRO(enif_clear_env) +# define enif_send ERL_NIF_API_FUNC_MACRO(enif_send) +# define enif_make_copy ERL_NIF_API_FUNC_MACRO(enif_make_copy) +# define enif_self ERL_NIF_API_FUNC_MACRO(enif_self) +# define enif_get_local_pid ERL_NIF_API_FUNC_MACRO(enif_get_local_pid) +# define enif_keep_resource ERL_NIF_API_FUNC_MACRO(enif_keep_resource) +# define enif_make_resource_binary ERL_NIF_API_FUNC_MACRO(enif_make_resource_binary) +#endif + +#ifndef enif_make_list1 +# define enif_make_list1(ENV,E1) enif_make_list(ENV,1,E1) +# define enif_make_list2(ENV,E1,E2) enif_make_list(ENV,2,E1,E2) +# define enif_make_list3(ENV,E1,E2,E3) enif_make_list(ENV,3,E1,E2,E3) +# define enif_make_list4(ENV,E1,E2,E3,E4) enif_make_list(ENV,4,E1,E2,E3,E4) +# define enif_make_list5(ENV,E1,E2,E3,E4,E5) enif_make_list(ENV,5,E1,E2,E3,E4,E5) +# define enif_make_list6(ENV,E1,E2,E3,E4,E5,E6) enif_make_list(ENV,6,E1,E2,E3,E4,E5,E6) +# define enif_make_list7(ENV,E1,E2,E3,E4,E5,E6,E7) enif_make_list(ENV,7,E1,E2,E3,E4,E5,E6,E7) +# define enif_make_list8(ENV,E1,E2,E3,E4,E5,E6,E7,E8) enif_make_list(ENV,8,E1,E2,E3,E4,E5,E6,E7,E8) +# define enif_make_list9(ENV,E1,E2,E3,E4,E5,E6,E7,E8,E9) enif_make_list(ENV,9,E1,E2,E3,E4,E5,E6,E7,E8,E9) +# define enif_make_tuple1(ENV,E1) enif_make_tuple(ENV,1,E1) +# define enif_make_tuple2(ENV,E1,E2) enif_make_tuple(ENV,2,E1,E2) +# define enif_make_tuple3(ENV,E1,E2,E3) enif_make_tuple(ENV,3,E1,E2,E3) +# define enif_make_tuple4(ENV,E1,E2,E3,E4) enif_make_tuple(ENV,4,E1,E2,E3,E4) +# define enif_make_tuple5(ENV,E1,E2,E3,E4,E5) enif_make_tuple(ENV,5,E1,E2,E3,E4,E5) +# define enif_make_tuple6(ENV,E1,E2,E3,E4,E5,E6) enif_make_tuple(ENV,6,E1,E2,E3,E4,E5,E6) +# define enif_make_tuple7(ENV,E1,E2,E3,E4,E5,E6,E7) enif_make_tuple(ENV,7,E1,E2,E3,E4,E5,E6,E7) +# define enif_make_tuple8(ENV,E1,E2,E3,E4,E5,E6,E7,E8) enif_make_tuple(ENV,8,E1,E2,E3,E4,E5,E6,E7,E8) +# define enif_make_tuple9(ENV,E1,E2,E3,E4,E5,E6,E7,E8,E9) enif_make_tuple(ENV,9,E1,E2,E3,E4,E5,E6,E7,E8,E9) + +# define enif_make_pid(ENV, PID) ((const ERL_NIF_TERM)((PID)->pid)) +#endif + diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.1.2_0.c b/erts/emulator/test/nif_SUITE_data/nif_mod.1.2_0.c new file mode 100644 index 0000000000..a554cc7f25 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.1.2_0.c @@ -0,0 +1,4 @@ +#include "nif_api_2_0/erl_nif.h" + +#define NIF_LIB_VER 1 +#include "nif_mod.c" diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.2.2_0.c b/erts/emulator/test/nif_SUITE_data/nif_mod.2.2_0.c new file mode 100644 index 0000000000..0731e6b5d0 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.2.2_0.c @@ -0,0 +1,4 @@ +#include "nif_api_2_0/erl_nif.h" + +#define NIF_LIB_VER 2 +#include "nif_mod.c" diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.3.2_0.c b/erts/emulator/test/nif_SUITE_data/nif_mod.3.2_0.c new file mode 100644 index 0000000000..d7e676b668 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.3.2_0.c @@ -0,0 +1,4 @@ +#include "nif_api_2_0/erl_nif.h" + +#define NIF_LIB_VER 3 +#include "nif_mod.c" -- cgit v1.2.3 From ece2fe5158d8a3212f5063572150ca991a66464c Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 25 Nov 2016 19:34:29 +0100 Subject: erts: Fix code_SUITE:api_2_0,upgrade crash on win64 --- erts/emulator/test/nif_SUITE.erl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 01a5e84dc9..0d3910b2e2 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -91,7 +91,13 @@ init_per_group(api_latest, Config) -> Config; init_per_group(api_2_4, Config) -> [{nif_api_version, ".2_4"} | Config]; init_per_group(api_2_0, Config) -> - [{nif_api_version, ".2_0"} | Config]. + case {os:type(),erlang:system_info({wordsize, internal})} of + {{win32,_}, 8} -> + %% ERL_NIF_TERM was declared as 32-bit 'long' until 2.3 + {skip, "API 2.0 buggy on Windows 64-bit"}; + _ -> + [{nif_api_version, ".2_0"} | Config] + end. end_per_group(_,_) -> ok. -- cgit v1.2.3 From b3441cbd116fede332e1e4cfee4d48331be1fa62 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 22 Nov 2016 13:39:24 +0100 Subject: erts: Add ?line macro for some hipe testing --- erts/emulator/test/code_SUITE.erl | 2 +- .../code_SUITE_data/call_purged_fun_tester.erl | 108 ++++++++++++--------- 2 files changed, 65 insertions(+), 45 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index 774461c525..0742b77a52 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -155,7 +155,7 @@ call_purged_fun_code_there(Config) when is_list(Config) -> call_purged_fun_test(Priv, Data, Type) -> OptsList = case erlang:system_info(hipe_architecture) of undefined -> [[]]; - _ -> [[], [native]] + _ -> [[], [native,{d,hipe}]] end, [call_purged_fun_test_do(Priv, Data, Type, CO, FO) || CO <- OptsList, FO <- OptsList]. diff --git a/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl b/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl index 5e031abca8..16dbbcec37 100644 --- a/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl +++ b/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl @@ -2,7 +2,27 @@ -export([do/4]). +%% Resurrect line macro when hipe compiled +-ifdef(hipe). +-define(line, put(the_line,?LINE),). do(Priv, Data, Type, Opts) -> + try do_it(Priv, Data, Type, Opts) + catch + C:E -> + ST = erlang:get_stacktrace(), + io:format("Caught exception from line ~p:\n~p\n", + [get(the_line), ST]), + io:format("Message queue: ~p\n", [process_info(self(), messages)]), + erlang:raise(C, E, ST) + end. +-else. +-define(line,). +do(P,D,T,O) -> + do_it(P,D,T,O). +-endif. + + +do_it(Priv, Data, Type, Opts) -> File = filename:join(Data, "my_code_test2"), Code = filename:join(Priv, "my_code_test2"), @@ -10,12 +30,12 @@ do(Priv, Data, Type, Opts) -> catch erlang:delete_module(my_code_test2), catch erlang:purge_module(my_code_test2), - {ok,my_code_test2} = c:c(File, [{outdir,Priv} | Opts]), + ?line {ok,my_code_test2} = c:c(File, [{outdir,Priv} | Opts]), - IsNative = lists:member(native,Opts), - IsNative = code:is_module_native(my_code_test2), + ?line IsNative = lists:member(native,Opts), + ?line IsNative = code:is_module_native(my_code_test2), - T = ets:new(my_code_test2_fun_table, []), + ?line T = ets:new(my_code_test2_fun_table, []), ets:insert(T, {my_fun,my_code_test2:make_fun(4711)}), ets:insert(T, {my_fun2,my_code_test2:make_fun2()}), @@ -28,7 +48,7 @@ do(Priv, Data, Type, Opts) -> exit(completed) end), - PurgeType = case Type of + ?line PurgeType = case Type of code_gone -> ok = file:delete(Code++".beam"), true; @@ -38,89 +58,89 @@ do(Priv, Data, Type, Opts) -> false end, - true = erlang:delete_module(my_code_test2), + ?line true = erlang:delete_module(my_code_test2), - Purge = start_purge(my_code_test2, PurgeType), + ?line Purge = start_purge(my_code_test2, PurgeType), - {P0, M0} = spawn_monitor(fun () -> - [{my_fun,F}] = ets:lookup(T, my_fun), - 4712 = F(1), - exit(completed) + ?line {P0, M0} = spawn_monitor(fun () -> + ?line [{my_fun,F}] = ets:lookup(T, my_fun), + ?line 4712 = F(1), + exit(completed) end), - wait_until(fun () -> - {status, suspended} - == process_info(P0, status) - end), + ?line ok = wait_until(fun () -> + {status, suspended} + == process_info(P0, status) + end), - ok = continue_purge(Purge), + ?line ok = continue_purge(Purge), - {P1, M1} = spawn_monitor(fun () -> - [{my_fun,F}] = ets:lookup(T, my_fun), - 4713 = F(2), - exit(completed) + ?line {P1, M1} = spawn_monitor(fun () -> + ?line [{my_fun,F}] = ets:lookup(T, my_fun), + ?line 4713 = F(2), + exit(completed) end), - {P2, M2} = spawn_monitor(fun () -> - [{my_fun,F}] = ets:lookup(T, my_fun), - 4714 = F(3), - exit(completed) + ?line {P2, M2} = spawn_monitor(fun () -> + ?line [{my_fun,F}] = ets:lookup(T, my_fun), + ?line 4714 = F(3), + exit(completed) end), - wait_until(fun () -> - {status, suspended} - == process_info(P1, status) - end), - wait_until(fun () -> - {status, suspended} - == process_info(P2, status) - end), + ?line ok = wait_until(fun () -> + {status, suspended} + == process_info(P1, status) + end), + ?line ok = wait_until(fun () -> + {status, suspended} + == process_info(P2, status) + end), - {current_function, + ?line {current_function, {erts_code_purger, pending_purge_lambda, 3}} = process_info(P0, current_function), - {current_function, + ?line {current_function, {erts_code_purger, pending_purge_lambda, 3}} = process_info(P1, current_function), - {current_function, + ?line {current_function, {erts_code_purger, pending_purge_lambda, 3}} = process_info(P2, current_function), case Type of code_there -> - false = complete_purge(Purge); + ?line false = complete_purge(Purge); _ -> - {true, true} = complete_purge(Purge) + ?line {true, true} = complete_purge(Purge) end, case Type of code_gone -> receive {'DOWN', M0, process, P0, Reason0} -> - {undef, _} = Reason0 + ?line {undef, _} = Reason0 end, receive {'DOWN', M1, process, P1, Reason1} -> - {undef, _} = Reason1 + ?line {undef, _} = Reason1 end, receive {'DOWN', M2, process, P2, Reason2} -> - {undef, _} = Reason2 + ?line {undef, _} = Reason2 end; _ -> receive {'DOWN', M0, process, P0, Reason0} -> - completed = Reason0 + ?line completed = Reason0 end, receive {'DOWN', M1, process, P1, Reason1} -> - completed = Reason1 + ?line completed = Reason1 end, receive {'DOWN', M2, process, P2, Reason2} -> - completed = Reason2 + ?line completed = Reason2 end, catch erlang:purge_module(my_code_test2), catch erlang:delete_module(my_code_test2), @@ -129,7 +149,7 @@ do(Priv, Data, Type, Opts) -> ok. wait_until(Fun) -> - ok = wait_until(Fun, 20). + wait_until(Fun, 20). wait_until(Fun, N) -> case {Fun(),N} of -- cgit v1.2.3 From 15789e168811d6e6bed082ea7c64db93e1d968e8 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 17 Nov 2016 14:39:04 +0100 Subject: erts: Refactor test code --- .../code_SUITE_data/call_purged_fun_tester.erl | 58 +++++++++------------- 1 file changed, 24 insertions(+), 34 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl b/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl index 16dbbcec37..10d00b7d2a 100644 --- a/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl +++ b/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl @@ -62,25 +62,25 @@ do_it(Priv, Data, Type, Opts) -> ?line Purge = start_purge(my_code_test2, PurgeType), - ?line {P0, M0} = spawn_monitor(fun () -> + ?line {P1, M1} = spawn_monitor(fun () -> ?line [{my_fun,F}] = ets:lookup(T, my_fun), ?line 4712 = F(1), exit(completed) end), - ?line ok = wait_until(fun () -> + ?line ok = wait_until(fun () -> {status, suspended} - == process_info(P0, status) + == process_info(P1, status) end), ?line ok = continue_purge(Purge), - ?line {P1, M1} = spawn_monitor(fun () -> + ?line {P2, M2} = spawn_monitor(fun () -> ?line [{my_fun,F}] = ets:lookup(T, my_fun), ?line 4713 = F(2), exit(completed) end), - ?line {P2, M2} = spawn_monitor(fun () -> + ?line {P3, M3} = spawn_monitor(fun () -> ?line [{my_fun,F}] = ets:lookup(T, my_fun), ?line 4714 = F(3), exit(completed) @@ -88,25 +88,25 @@ do_it(Priv, Data, Type, Opts) -> ?line ok = wait_until(fun () -> {status, suspended} - == process_info(P1, status) + == process_info(P2, status) end), ?line ok = wait_until(fun () -> {status, suspended} - == process_info(P2, status) + == process_info(P3, status) end), ?line {current_function, {erts_code_purger, pending_purge_lambda, - 3}} = process_info(P0, current_function), + 3}} = process_info(P1, current_function), ?line {current_function, {erts_code_purger, pending_purge_lambda, - 3}} = process_info(P1, current_function), + 3}} = process_info(P2, current_function), ?line {current_function, {erts_code_purger, pending_purge_lambda, - 3}} = process_info(P2, current_function), + 3}} = process_info(P3, current_function), case Type of code_there -> @@ -117,37 +117,27 @@ do_it(Priv, Data, Type, Opts) -> case Type of code_gone -> - receive - {'DOWN', M0, process, P0, Reason0} -> - ?line {undef, _} = Reason0 - end, - receive - {'DOWN', M1, process, P1, Reason1} -> - ?line {undef, _} = Reason1 - end, - receive - {'DOWN', M2, process, P2, Reason2} -> - ?line {undef, _} = Reason2 - end; + ?line {undef, _} = wait_for_down(P1,M1), + ?line {undef, _} = wait_for_down(P2,M2), + ?line {undef, _} = wait_for_down(P3,M3); _ -> - receive - {'DOWN', M0, process, P0, Reason0} -> - ?line completed = Reason0 - end, - receive - {'DOWN', M1, process, P1, Reason1} -> - ?line completed = Reason1 - end, - receive - {'DOWN', M2, process, P2, Reason2} -> - ?line completed = Reason2 - end, + ?line completed = wait_for_down(P1,M1), + ?line completed = wait_for_down(P2,M2), + ?line completed = wait_for_down(P3,M3), catch erlang:purge_module(my_code_test2), catch erlang:delete_module(my_code_test2), catch erlang:purge_module(my_code_test2) end, ok. +wait_for_down(P,M) -> + receive + {'DOWN', M, process, P, Reason} -> + Reason + after 1000 -> + timeout + end. + wait_until(Fun) -> wait_until(Fun, 20). -- cgit v1.2.3 From 20eea6a99b25b99db728fcae5b8303739e5c1cc8 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 17 Nov 2016 17:35:17 +0100 Subject: erts: Fix race in code_SUITE:call_purged_fun_* Must wait for process P0 to enter fun F2 before starting purge, to make sure it's not suspended. --- .../code_SUITE_data/call_purged_fun_tester.erl | 29 ++++++++++++++-------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl b/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl index 10d00b7d2a..699f0c1161 100644 --- a/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl +++ b/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl @@ -39,14 +39,16 @@ do_it(Priv, Data, Type, Opts) -> ets:insert(T, {my_fun,my_code_test2:make_fun(4711)}), ets:insert(T, {my_fun2,my_code_test2:make_fun2()}), - spawn(fun () -> - [{my_fun2,F2}] = ets:lookup(T, my_fun2), - F2(fun () -> - receive after infinity -> ok end - end, - fun () -> ok end), - exit(completed) - end), + Papa = self(), + {P0,M0} = spawn_monitor(fun () -> + [{my_fun2,F2}] = ets:lookup(T, my_fun2), + F2(fun () -> + Papa ! {self(),"going to sleep"}, + receive {Papa,"wake up"} -> ok end + end, + fun () -> ok end), + exit(completed) + end), ?line PurgeType = case Type of code_gone -> @@ -60,6 +62,10 @@ do_it(Priv, Data, Type, Opts) -> ?line true = erlang:delete_module(my_code_test2), + ?line ok = receive {P0, "going to sleep"} -> ok + after 1000 -> timeout + end, + ?line Purge = start_purge(my_code_test2, PurgeType), ?line {P1, M1} = spawn_monitor(fun () -> @@ -110,9 +116,12 @@ do_it(Priv, Data, Type, Opts) -> case Type of code_there -> - ?line false = complete_purge(Purge); + ?line false = complete_purge(Purge), + P0 ! {self(), "wake up"}, + ?line completed = wait_for_down(P0,M0); _ -> - ?line {true, true} = complete_purge(Purge) + ?line {true, true} = complete_purge(Purge), + ?line killed = wait_for_down(P0,M0) end, case Type of -- cgit v1.2.3 From 0763a36867a702e3075b682973a079e0390144ce Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 23 Nov 2016 15:58:15 +0100 Subject: erts: Add enif_select & enif_open_resource_type_x --- erts/emulator/test/nif_SUITE.erl | 43 ++++++ erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 190 +++++++++++++++++++++++++- 2 files changed, 231 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 0d3910b2e2..8c761202d6 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -31,6 +31,7 @@ init_per_testcase/2, end_per_testcase/2, basic/1, reload_error/1, upgrade/1, heap_frag/1, t_on_load/1, + select/1, hipe/1, types/1, many_args/1, binaries/1, get_string/1, get_atom/1, maps/1, @@ -64,6 +65,7 @@ all() -> [{group, G} || G <- api_groups()] ++ [reload_error, heap_frag, types, many_args, + select, hipe, binaries, get_string, get_atom, maps, api_macros, from_array, iolist_as_binary, resource, resource_binary, @@ -434,6 +436,33 @@ t_on_load(Config) when is_list(Config) -> verify_tmpmem(TmpMem), ok. +-define(ERL_NIF_SELECT_READ, (1 bsl 0)). +-define(ERL_NIF_SELECT_WRITE, (1 bsl 1)). +-define(ERL_NIF_SELECT_STOP, (1 bsl 2)). + +select(Config) when is_list(Config) -> + ensure_lib_loaded(Config), + + Ref = make_ref(), + {R,W} = pipe_nif(), + ok = write_nif(W, <<"hej">>), + <<"hej">> = read_nif(R, 3), + eagain = read_nif(R, 3), + 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,Ref), + [] = flush(), + ok = write_nif(W, <<"hej">>), + [{select, R, Ref, ready_input}] = flush(), + <<"hej">> = read_nif(R, 3), + + %% To be extended... + + 0 = select_nif(R,?ERL_NIF_SELECT_STOP,R,Ref), + 0 = select_nif(W,?ERL_NIF_SELECT_STOP,W,Ref), + timer:sleep(10), + true = is_closed_nif(R), + true = is_closed_nif(W), + ok. + hipe(Config) when is_list(Config) -> Data = proplists:get_value(data_dir, Config), Priv = proplists:get_value(priv_dir, Config), @@ -1910,6 +1939,15 @@ call(Pid,Cmd) -> receive_any() -> receive M -> M end. +flush() -> + flush(10). +flush(Timeout) -> + receive M -> + [M | flush(Timeout)] + after Timeout -> + [] + end. + repeat(0, _, Arg) -> Arg; repeat(N, Fun, Arg0) -> @@ -2273,6 +2311,11 @@ term_to_binary_nif(_, _) -> ?nif_stub. binary_to_term_nif(_, _, _) -> ?nif_stub. port_command_nif(_, _) -> ?nif_stub. format_term_nif(_,_) -> ?nif_stub. +select_nif(_,_,_,_) -> ?nif_stub. +pipe_nif() -> ?nif_stub. +write_nif(_,_) -> ?nif_stub. +read_nif(_,_) -> ?nif_stub. +is_closed_nif(_) -> ?nif_stub. %% maps is_map_nif(_) -> ?nif_stub. diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 2c93891852..a4915b13c4 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -25,6 +25,8 @@ #include #ifndef __WIN32__ #include +#include +#include #endif #include "nif_mod.h" @@ -42,7 +44,9 @@ static ERL_NIF_TERM atom_second; static ERL_NIF_TERM atom_millisecond; static ERL_NIF_TERM atom_microsecond; static ERL_NIF_TERM atom_nanosecond; - +static ERL_NIF_TERM atom_eagain; +static ERL_NIF_TERM atom_eof; +static ERL_NIF_TERM atom_error; typedef struct { @@ -102,6 +106,18 @@ struct binary_resource { unsigned size; }; +static ErlNifResourceType* fd_resource_type; +static void fd_resource_dtor(ErlNifEnv* env, void* obj); +static void fd_resource_stop(ErlNifEnv* env, void* obj); +static ErlNifResourceTypeInit fd_rt_init = { + fd_resource_dtor, + fd_resource_stop +}; +struct fd_resource { + int fd; +}; + + static int get_pointer(ErlNifEnv* env, ERL_NIF_TERM term, void** pp) { ErlNifBinary bin; @@ -144,6 +160,9 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) msgenv_resource_type = enif_open_resource_type(env,NULL,"nif_SUITE.msgenv", msgenv_dtor, ERL_NIF_RT_CREATE, NULL); + fd_resource_type = enif_open_resource_type_x(env, "nif_SUITE.fd", + &fd_rt_init, + ERL_NIF_RT_CREATE, NULL); atom_false = enif_make_atom(env,"false"); atom_true = enif_make_atom(env,"true"); atom_self = enif_make_atom(env,"self"); @@ -154,6 +173,9 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_millisecond = enif_make_atom(env,"millisecond"); atom_microsecond = enif_make_atom(env,"microsecond"); atom_nanosecond = enif_make_atom(env,"nanosecond"); + atom_eagain = enif_make_atom(env, "eagain"); + atom_eof = enif_make_atom(env, "eof"); + atom_error = enif_make_atom(env, "error"); *priv_data = data; return 0; @@ -2010,6 +2032,165 @@ static ERL_NIF_TERM format_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg } +static int get_fd(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifEvent* fd) +{ + struct fd_resource* rsrc; + + if (!enif_get_resource(env, term, fd_resource_type, (void**)&rsrc)) { + return 0; + } + *fd = rsrc->fd; + return 1; +} + +static ERL_NIF_TERM select_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ErlNifEvent e; + enum ErlNifSelectFlags mode; + void* obj; + ERL_NIF_TERM ref; + int retval; + + if (!get_fd(env, argv[0], &e) + || !enif_get_uint(env, argv[1], &mode) + || !enif_get_resource(env, argv[2], fd_resource_type, &obj)) + { + return enif_make_badarg(env); + } + + ref = argv[3]; + + retval = enif_select(env, e, mode, obj, ref); + + return enif_make_int(env, retval); +} + +static ERL_NIF_TERM pipe_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + struct fd_resource* read_rsrc; + struct fd_resource* write_rsrc; + ERL_NIF_TERM read_fd, write_fd; + unsigned char *inp, *outp; + int fds[2], flags; + + if (pipe(fds) < 0) + return enif_make_string(env, "pipe failed", ERL_NIF_LATIN1); + + if ((flags = fcntl(fds[0], F_GETFL, 0)) < 0 + || fcntl(fds[0], F_SETFL, flags|O_NONBLOCK) < 0 + || (flags = fcntl(fds[1], F_GETFL, 0)) < 0 + || fcntl(fds[1], F_SETFL, flags|O_NONBLOCK) < 0) { + close(fds[0]); + close(fds[1]); + return enif_make_string(env, "fcntl failed on pipe", ERL_NIF_LATIN1); + } + + read_rsrc = enif_alloc_resource(fd_resource_type, sizeof(struct fd_resource)); + write_rsrc = enif_alloc_resource(fd_resource_type, sizeof(struct fd_resource)); + read_rsrc->fd = fds[0]; + write_rsrc->fd = fds[1]; + read_fd = enif_make_resource(env, read_rsrc); + write_fd = enif_make_resource(env, write_rsrc); + enif_release_resource(read_rsrc); + enif_release_resource(write_rsrc); + + return enif_make_tuple2(env, read_fd, write_fd); +} + +static ERL_NIF_TERM write_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ErlNifEvent fd; + ErlNifBinary bin; + int n, written = 0; + + if (!get_fd(env, argv[0], &fd) + || !enif_inspect_binary(env, argv[1], &bin)) + return enif_make_badarg(env); + + for (;;) { + n = write(fd, bin.data + written, bin.size - written); + if (n >= 0) { + written += n; + if (written == bin.size) { + return atom_ok; + } + } + else if (errno == EAGAIN) { + return enif_make_tuple2(env, atom_eagain, enif_make_int(env, written)); + } + else if (errno == EINTR) { + continue; + } + else { + return enif_make_tuple2(env, atom_error, enif_make_int(env, errno)); + } + } +} + +static ERL_NIF_TERM read_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ErlNifEvent fd; + unsigned char* buf; + int n, count, nread = 0; + ERL_NIF_TERM res; + + if (!get_fd(env, argv[0], &fd) + || !enif_get_int(env, argv[1], &count) || count < 1) + return enif_make_badarg(env); + + buf = enif_make_new_binary(env, count, &res); + + for (;;) { + n = read(fd, buf, count); + if (n > 0) { + if (n < count) { + res = enif_make_sub_binary(env, res, 0, n); + } + return res; + } + else if (n == 0) { + return atom_eof; + } + else if (errno == EAGAIN) { + return atom_eagain; + } + else if (errno == EINTR) { + continue; + } + else { + return enif_make_tuple2(env, atom_error, enif_make_int(env, errno)); + } + } +} + +static ERL_NIF_TERM is_closed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ErlNifEvent fd; + + if (!get_fd(env, argv[0], &fd)) + return enif_make_badarg(env); + + return fd < 0 ? atom_true : atom_false; +} + +static void fd_resource_dtor(ErlNifEnv* env, void* obj) +{ + struct fd_resource* rsrc = (struct fd_resource*)obj; + if (rsrc->fd >= 0) + close(rsrc->fd); +} + +static void fd_resource_stop(ErlNifEnv* env, void* obj) +{ + struct fd_resource* rsrc = (struct fd_resource*)obj; + if (rsrc->fd >= 0) { + close(rsrc->fd); + rsrc->fd = -1; /* thread safety ? */ + } +} + + + static ErlNifFunc nif_funcs[] = { {"lib_version", 0, lib_version}, @@ -2086,7 +2267,12 @@ static ErlNifFunc nif_funcs[] = {"term_to_binary_nif", 2, term_to_binary}, {"binary_to_term_nif", 3, binary_to_term}, {"port_command_nif", 2, port_command}, - {"format_term_nif", 2, format_term} + {"format_term_nif", 2, format_term}, + {"select_nif", 4, select_nif}, + {"pipe_nif", 0, pipe_nif}, + {"write_nif", 2, write_nif}, + {"read_nif", 2, read_nif}, + {"is_closed_nif", 1, is_closed_nif} }; ERL_NIF_INIT(nif_SUITE,nif_funcs,load,NULL,upgrade,unload) -- cgit v1.2.3 From 3eddb0f762de248d3230b38bc9d478bfbc8e7331 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Wed, 7 Dec 2016 13:15:31 +0100 Subject: Update copyright-year --- erts/emulator/test/dirty_nif_SUITE.erl | 2 +- erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c | 2 +- erts/emulator/test/lttng_SUITE.erl | 2 +- erts/emulator/test/port_trace_SUITE.erl | 2 +- erts/emulator/test/tracer_SUITE.erl | 2 +- erts/emulator/test/tracer_SUITE_data/tracer_test.c | 2 +- erts/emulator/test/tracer_test.erl | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/dirty_nif_SUITE.erl b/erts/emulator/test/dirty_nif_SUITE.erl index 658bdc41b6..a61fd92a18 100644 --- a/erts/emulator/test/dirty_nif_SUITE.erl +++ b/erts/emulator/test/dirty_nif_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2014. All Rights Reserved. +%% Copyright Ericsson AB 2010-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c index a0019e5d95..08efa23c81 100644 --- a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c +++ b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2009-2014. All Rights Reserved. + * Copyright Ericsson AB 2009-2016. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/lttng_SUITE.erl b/erts/emulator/test/lttng_SUITE.erl index 6b7ad836f5..c12f63706a 100644 --- a/erts/emulator/test/lttng_SUITE.erl +++ b/erts/emulator/test/lttng_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2011. All Rights Reserved. +%% Copyright Ericsson AB 1999-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/port_trace_SUITE.erl b/erts/emulator/test/port_trace_SUITE.erl index 5d9a75bcd3..03efdc15db 100644 --- a/erts/emulator/test/port_trace_SUITE.erl +++ b/erts/emulator/test/port_trace_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2012. All Rights Reserved. +%% Copyright Ericsson AB 1999-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/tracer_SUITE.erl b/erts/emulator/test/tracer_SUITE.erl index 9eb55c9af3..730c43d8c2 100644 --- a/erts/emulator/test/tracer_SUITE.erl +++ b/erts/emulator/test/tracer_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2013. All Rights Reserved. +%% Copyright Ericsson AB 1997-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/tracer_SUITE_data/tracer_test.c b/erts/emulator/test/tracer_SUITE_data/tracer_test.c index a26bb33600..d9543b7ab9 100644 --- a/erts/emulator/test/tracer_SUITE_data/tracer_test.c +++ b/erts/emulator/test/tracer_SUITE_data/tracer_test.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2009-2014. All Rights Reserved. + * Copyright Ericsson AB 2009-2016. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/tracer_test.erl b/erts/emulator/test/tracer_test.erl index 1da80bfe31..a82fd04d2e 100644 --- a/erts/emulator/test/tracer_test.erl +++ b/erts/emulator/test/tracer_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2013. All Rights Reserved. +%% Copyright Ericsson AB 1997-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. -- cgit v1.2.3 From a07fc6fbcdf270e29332cd2556511b5f04e3d476 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 8 Dec 2016 18:36:25 +0100 Subject: erts: Fix hanging race in code_SUITE:versions Monitor first, then ask to terminate. --- erts/emulator/test/code_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index 34515efa3d..3ee14f2d1c 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -66,9 +66,9 @@ versions(Config) when is_list(Config) -> 2 = versions:version(), %% Kill processes, unload code. - P1 ! P2 ! done, _ = monitor(process, P1), _ = monitor(process, P2), + P1 ! P2 ! done, receive {'DOWN',_,process,P1,normal} -> ok end, -- cgit v1.2.3 From 2e1fb1a42098ac73cd44f60699a09c3c3e49f77f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 12 Dec 2016 16:24:49 +0100 Subject: Don't include problematic test cases in smoke test In time_SUITE, the univ_to_local/1 and local_to_univ/1 test cases will fail if they are run outside the CET timezone. The consistency/1 test case uses is not reliable in March and October because it uses a simplified model for when the switch to/from DST is done. --- erts/emulator/test/emulator_smoke.spec | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/emulator_smoke.spec b/erts/emulator/test/emulator_smoke.spec index 3219aeb823..b2d0de8835 100644 --- a/erts/emulator/test/emulator_smoke.spec +++ b/erts/emulator/test/emulator_smoke.spec @@ -1,3 +1,9 @@ -{suites,"../emulator_test",[smoke_test_SUITE,time_SUITE]}. -{cases,"../emulator_test",crypto_SUITE,[t_md5]}. -{cases,"../emulator_test",float_SUITE,[fpe,cmp_integer]}. \ No newline at end of file +{define,'Dir',"../emulator_test"}. +{suites,'Dir',[smoke_test_SUITE]}. +{suites,'Dir',[time_SUITE]}. +{skip_cases,'Dir',time_SUITE, + [univ_to_local,local_to_univ],"Depends on CET timezone"}. +{skip_cases,'Dir',time_SUITE, + [consistency],"Not reliable in October and March"}. +{cases,'Dir',crypto_SUITE,[t_md5]}. +{cases,'Dir',float_SUITE,[fpe,cmp_integer]}. -- cgit v1.2.3 From 2f8d59aa9e8a96d094172db339fd94aae45a90b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Mattsson?= Date: Wed, 2 Nov 2016 12:56:39 +0100 Subject: erts: Make depth of current_stacktrace configurable The BIF process_info(Pid, current_stacktrace) truncates the stacktrace. The old behavior was to truncate long stacktraces to max 8 items. And this was hard coded. Now it is truncated to the value of system_flag(backtrace_depth) instead. The backtrace_depth defaults to 8, but is configurable. --- erts/emulator/test/process_SUITE.erl | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index 0f999e0efe..2289cbabc7 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -437,11 +437,22 @@ t_process_info(Config) when is_list(Config) -> verify_loc(Line2, Res2), pi_stacktrace([{?MODULE,t_process_info,1,?LINE}]), + verify_stacktrace_depth(), + Gleader = group_leader(), {group_leader, Gleader} = process_info(self(), group_leader), {'EXIT',{badarg,_Info}} = (catch process_info('not_a_pid')), ok. +verify_stacktrace_depth() -> + CS = current_stacktrace, + OldDepth = erlang:system_flag(backtrace_depth, 0), + {CS,[]} = erlang:process_info(self(), CS), + _ = erlang:system_flag(backtrace_depth, 8), + {CS,[{?MODULE,verify_stacktrace_depth,0,_},_|_]} = + erlang:process_info(self(), CS), + _ = erlang:system_flag(backtrace_depth, OldDepth). + pi_stacktrace(Expected0) -> {Line,Res} = {?LINE,erlang:process_info(self(), current_stacktrace)}, {current_stacktrace,Stack} = Res, -- cgit v1.2.3 From f5627a66cec1b2e75264ee17b38f1e6d794bb671 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 10 Nov 2016 19:55:40 +0100 Subject: erts: Fix faulty printout in port_SUITE --- erts/emulator/test/port_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index d4e77d634a..23594aa8c4 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -2292,7 +2292,7 @@ maybe_to_list(List) -> List. format({Eol,List}) -> - io_lib:format("tuple<~w,~s>",[Eol, maybe_to_list(List)]); + io_lib:format("tuple<~w,~w>",[Eol, maybe_to_list(List)]); format(List) when is_list(List) -> case list_at_least(50, List) of true -> -- cgit v1.2.3 From d44f2e85c058e10082427a354a7d65e9af607501 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Fri, 25 Nov 2016 15:03:33 +0100 Subject: Fix stack-trace generated by a traced process --- erts/emulator/test/call_trace_SUITE.erl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/call_trace_SUITE.erl b/erts/emulator/test/call_trace_SUITE.erl index 6ba6301c7c..f7ff04430a 100644 --- a/erts/emulator/test/call_trace_SUITE.erl +++ b/erts/emulator/test/call_trace_SUITE.erl @@ -1090,8 +1090,7 @@ exception_nocatch() -> {trace,t2,exception_from,{erlang,throw,1}, {error,{nocatch,Q2}}}], exception_from, {error,{nocatch,Q2}}), - expect({trace,T2,exit,{{nocatch,Q2},[{erlang,throw,[Q2],[]}, - {?MODULE,deep_4,1, + expect({trace,T2,exit,{{nocatch,Q2},[{?MODULE,deep_4,1, Deep4LocThrow}]}}), Q3 = {dump,[dump,{dump}]}, T3 = @@ -1100,8 +1099,7 @@ exception_nocatch() -> {trace,t3,exception_from,{erlang,error,1}, {error,Q3}}], exception_from, {error,Q3}), - expect({trace,T3,exit,{Q3,[{erlang,error,[Q3],[]}, - {?MODULE,deep_4,1,Deep4LocError}]}}), + expect({trace,T3,exit,{Q3,[{?MODULE,deep_4,1,Deep4LocError}]}}), T4 = exception_nocatch(?LINE, '=', [17,4711], 5, [], exception_from, {error,{badmatch,4711}}), -- cgit v1.2.3 From cece1693410a89e87343367e86b5dd82ac0e73b7 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Wed, 30 Nov 2016 16:46:26 +0100 Subject: New test cases testing stacktrace from apply on erlang:error() --- erts/emulator/test/bif_SUITE.erl | 173 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 170 insertions(+), 3 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl index b8d89126fe..f70fb0e501 100644 --- a/erts/emulator/test/bif_SUITE.erl +++ b/erts/emulator/test/bif_SUITE.erl @@ -32,7 +32,8 @@ binary_to_atom/1,binary_to_existing_atom/1, atom_to_binary/1,min_max/1, erlang_halt/1, erl_crash_dump_bytes/1, - is_builtin/1]). + is_builtin/1, error_stacktrace/1, + error_stacktrace_during_call_trace/1]). suite() -> [{ct_hooks,[ts_install_cth]}, @@ -44,8 +45,8 @@ all() -> t_list_to_existing_atom, os_env, otp_7526, display, atom_to_binary, binary_to_atom, binary_to_existing_atom, - erl_crash_dump_bytes, - min_max, erlang_halt, is_builtin]. + erl_crash_dump_bytes, min_max, erlang_halt, is_builtin, + error_stacktrace, error_stacktrace_during_call_trace]. %% Uses erlang:display to test that erts_printf does not do deep recursion display(Config) when is_list(Config) -> @@ -727,6 +728,172 @@ is_builtin(_Config) -> ok. +error_stacktrace(Config) when is_list(Config) -> + error_stacktrace_test(). + +error_stacktrace_during_call_trace(Config) when is_list(Config) -> + Tracer = spawn_link(fun () -> + receive after infinity -> ok end + end), + Mprog = [{'_',[],[{exception_trace}]}], + erlang:trace_pattern({?MODULE,'_','_'}, Mprog, [local]), + 1 = erlang:trace_pattern({erlang,error,2}, Mprog, [local]), + 1 = erlang:trace_pattern({erlang,error,1}, Mprog, [local]), + erlang:trace(all, true, [call,return_to,timestamp,{tracer, Tracer}]), + try + error_stacktrace_test() + after + erlang:trace(all, false, [call,return_to,timestamp,{tracer, Tracer}]), + erlang:trace_pattern({erlang,error,2}, false, [local]), + erlang:trace_pattern({erlang,error,1}, false, [local]), + erlang:trace_pattern({?MODULE,'_','_'}, false, [local]), + unlink(Tracer), + exit(Tracer, kill), + Mon = erlang:monitor(process, Tracer), + receive + {'DOWN', Mon, process, Tracer, _} -> ok + end + end, + ok. + + +error_stacktrace_test() -> + Types = [apply_const_last, apply_const, apply_last, + apply, double_apply_const_last, double_apply_const, + double_apply_last, double_apply, multi_apply_const_last, + multi_apply_const, multi_apply_last, multi_apply, + call_const_last, call_last, call_const, call], + lists:foreach(fun (Type) -> + {Pid, Mon} = spawn_monitor( + fun () -> + stk([a,b,c,d], Type, error_2) + end), + receive + {'DOWN', Mon, process, Pid, Reason} -> + {oops, Stack} = Reason, +%% io:format("Type: ~p Stack: ~p~n", +%% [Type, Stack]), + [{?MODULE, do_error_2, [Type], _}, + {?MODULE, stk, 3, _}, + {?MODULE, stk, 3, _}] = Stack + end + end, + Types), + lists:foreach(fun (Type) -> + {Pid, Mon} = spawn_monitor( + fun () -> + stk([a,b,c,d], Type, error_1) + end), + receive + {'DOWN', Mon, process, Pid, Reason} -> + {oops, Stack} = Reason, +%% io:format("Type: ~p Stack: ~p~n", +%% [Type, Stack]), + [{?MODULE, do_error_1, 1, _}, + {?MODULE, stk, 3, _}, + {?MODULE, stk, 3, _}] = Stack + end + end, + Types), + ok. + +stk([], Type, Func) -> + tail(Type, Func, jump), + ok; +stk([_|L], Type, Func) -> + stk(L, Type, Func), + ok. + +tail(Type, Func, jump) -> + tail(Type, Func, do); +tail(Type, error_1, do) -> + do_error_1(Type); +tail(Type, error_2, do) -> + do_error_2(Type). + +do_error_2(apply_const_last) -> + erlang:apply(erlang, error, [oops, [apply_const_last]]); +do_error_2(apply_const) -> + erlang:apply(erlang, error, [oops, [apply_const]]), + ok; +do_error_2(apply_last) -> + erlang:apply(id(erlang), id(error), id([oops, [apply_last]])); +do_error_2(apply) -> + erlang:apply(id(erlang), id(error), id([oops, [apply]])), + ok; +do_error_2(double_apply_const_last) -> + erlang:apply(erlang, apply, [erlang, error, [oops, [double_apply_const_last]]]); +do_error_2(double_apply_const) -> + erlang:apply(erlang, apply, [erlang, error, [oops, [double_apply_const]]]), + ok; +do_error_2(double_apply_last) -> + erlang:apply(id(erlang), id(apply), [id(erlang), id(error), id([oops, [double_apply_last]])]); +do_error_2(double_apply) -> + erlang:apply(id(erlang), id(apply), [id(erlang), id(error), id([oops, [double_apply]])]), + ok; +do_error_2(multi_apply_const_last) -> + erlang:apply(erlang, apply, [erlang, apply, [erlang, apply, [erlang, error, [oops, [multi_apply_const_last]]]]]); +do_error_2(multi_apply_const) -> + erlang:apply(erlang, apply, [erlang, apply, [erlang, apply, [erlang, error, [oops, [multi_apply_const]]]]]), + ok; +do_error_2(multi_apply_last) -> + erlang:apply(id(erlang), id(apply), [id(erlang), id(apply), [id(erlang), id(apply), [id(erlang), id(error), id([oops, [multi_apply_last]])]]]); +do_error_2(multi_apply) -> + erlang:apply(id(erlang), id(apply), [id(erlang), id(apply), [id(erlang), id(apply), [id(erlang), id(error), id([oops, [multi_apply]])]]]), + ok; +do_error_2(call_const_last) -> + erlang:error(oops, [call_const_last]); +do_error_2(call_last) -> + erlang:error(id(oops), id([call_last])); +do_error_2(call_const) -> + erlang:error(oops, [call_const]), + ok; +do_error_2(call) -> + erlang:error(id(oops), id([call])). + + +do_error_1(apply_const_last) -> + erlang:apply(erlang, error, [oops]); +do_error_1(apply_const) -> + erlang:apply(erlang, error, [oops]), + ok; +do_error_1(apply_last) -> + erlang:apply(id(erlang), id(error), id([oops])); +do_error_1(apply) -> + erlang:apply(id(erlang), id(error), id([oops])), + ok; +do_error_1(double_apply_const_last) -> + erlang:apply(erlang, apply, [erlang, error, [oops]]); +do_error_1(double_apply_const) -> + erlang:apply(erlang, apply, [erlang, error, [oops]]), + ok; +do_error_1(double_apply_last) -> + erlang:apply(id(erlang), id(apply), [id(erlang), id(error), id([oops])]); +do_error_1(double_apply) -> + erlang:apply(id(erlang), id(apply), [id(erlang), id(error), id([oops])]), + ok; +do_error_1(multi_apply_const_last) -> + erlang:apply(erlang, apply, [erlang, apply, [erlang, apply, [erlang, error, [oops]]]]); +do_error_1(multi_apply_const) -> + erlang:apply(erlang, apply, [erlang, apply, [erlang, apply, [erlang, error, [oops]]]]), + ok; +do_error_1(multi_apply_last) -> + erlang:apply(id(erlang), id(apply), [id(erlang), id(apply), [id(erlang), id(apply), [id(erlang), id(error), id([oops])]]]); +do_error_1(multi_apply) -> + erlang:apply(id(erlang), id(apply), [id(erlang), id(apply), [id(erlang), id(apply), [id(erlang), id(error), id([oops])]]]), + ok; +do_error_1(call_const_last) -> + erlang:error(oops); +do_error_1(call_last) -> + erlang:error(id(oops)); +do_error_1(call_const) -> + erlang:error(oops), + ok; +do_error_1(call) -> + erlang:error(id(oops)). + + + %% Helpers -- cgit v1.2.3 From 9e334f98679ace2c0fb7b9893c962a9d1a80e41c Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 7 Dec 2016 17:24:10 +0100 Subject: erts: Add ERL_ABORT_ON_FAILURE for driver_SUITE --- erts/emulator/test/driver_SUITE_data/chkio_drv.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/driver_SUITE_data/chkio_drv.c b/erts/emulator/test/driver_SUITE_data/chkio_drv.c index 614b68e865..8e5e81665c 100644 --- a/erts/emulator/test/driver_SUITE_data/chkio_drv.c +++ b/erts/emulator/test/driver_SUITE_data/chkio_drv.c @@ -1397,10 +1397,18 @@ static void assert_print(char* str, int line) static void assert_failed(ErlDrvPort port, char* str, int line) { char buf[30]; + size_t bufsz = sizeof(buf); + assert_print(str,line); - snprintf(buf,sizeof(buf),"failed_at_line_%d",line); - driver_failure_atom(port,buf); - /*abort();*/ + + if (erl_drv_getenv("ERL_ABORT_ON_FAILURE", buf, &bufsz) == 0 + && (strcmp("true", buf) == 0 || strcmp("yes", buf) == 0)) { + abort(); + } + else { + snprintf(buf,sizeof(buf),"failed_at_line_%d",line); + driver_failure_atom(port,buf); + } } #define my_driver_select(PORT,FD,MODE,ON) \ -- cgit v1.2.3 From 9ffe2d285943b661317cee2b00d779a2e75a3374 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 1 Dec 2016 19:54:22 +0100 Subject: erts: Add testing + some minor fixes --- erts/emulator/test/nif_SUITE.erl | 85 ++++++++++++++++++++++++++- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 1 + 2 files changed, 84 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 8c761202d6..2401ff708c 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -447,6 +447,8 @@ select(Config) when is_list(Config) -> {R,W} = pipe_nif(), ok = write_nif(W, <<"hej">>), <<"hej">> = read_nif(R, 3), + + %% Wait for read eagain = read_nif(R, 3), 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,Ref), [] = flush(), @@ -454,15 +456,94 @@ select(Config) when is_list(Config) -> [{select, R, Ref, ready_input}] = flush(), <<"hej">> = read_nif(R, 3), - %% To be extended... + %% Wait for write + Written = write_full(W, $a), + 0 = select_nif(W,?ERL_NIF_SELECT_WRITE,W,Ref), + [] = flush(), + Half = byte_size(Written) div 2, + <> = Written, + First = read_nif(R,Half), + [{select, W, Ref, ready_output}] = flush(), + Third = write_full(W, $A), + Half2 = byte_size(Second), + <> = read_nif(R, byte_size(Written)), + + %% Close write and wait for EOF + eagain = read_nif(R, 1), + 0 = select_nif(W,?ERL_NIF_SELECT_STOP,W,Ref), + timer:sleep(10), + true = is_closed_nif(W), + [] = flush(), + 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,Ref), + [{select, R, Ref, ready_input}] = flush(), + eof = read_nif(R,1), 0 = select_nif(R,?ERL_NIF_SELECT_STOP,R,Ref), - 0 = select_nif(W,?ERL_NIF_SELECT_STOP,W,Ref), + timer:sleep(10), + true = is_closed_nif(R), + + select_2(Config). + +select_2(Config) -> + erlang:garbage_collect(), + {_,_,2} = last_resource_dtor_call(), + + Ref1 = make_ref(), + Ref2 = make_ref(), + {R,W} = pipe_nif(), + + %% Change ref + eagain = read_nif(R, 1), + 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,Ref1), + 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,Ref2), + + [] = flush(), + ok = write_nif(W, <<"hej">>), + [{select, R, Ref2, ready_input}] = flush(), + <<"hej">> = read_nif(R, 3), + + %% Change pid + eagain = read_nif(R, 1), + 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,Ref1), + Papa = self(), + Pid2 = spawn_link(fun() -> + 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,Ref1), + [] = flush(), + Papa ! sync, + [{select, R, Ref1, ready_input}] = flush(), + <<"hej">> = read_nif(R, 3), + Papa ! done + end), + sync = receive_any(), + ok = write_nif(W, <<"hej">>), + done = receive_any(), + [] = flush(), + + 0 = select_nif(R,?ERL_NIF_SELECT_STOP,R,Ref1), + 0 = select_nif(W,?ERL_NIF_SELECT_STOP,W,Ref1), timer:sleep(10), true = is_closed_nif(R), true = is_closed_nif(W), + + select_3(Config). + +select_3(Config) -> + erlang:garbage_collect(), + {_,_,2} = last_resource_dtor_call(), ok. + + +write_full(W, C) -> + write_full(W, C, <<>>). +write_full(W, C, Acc) -> + case write_nif(W, <>) of + ok -> + write_full(W, (C+1) band 255, <>); + {eagain,0} -> + Acc + end. + hipe(Config) when is_list(Config) -> Data = proplists:get_value(data_dir, Config), Priv = proplists:get_value(priv_dir, Config), diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index a4915b13c4..f6ccd3e6ba 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -2176,6 +2176,7 @@ static ERL_NIF_TERM is_closed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a static void fd_resource_dtor(ErlNifEnv* env, void* obj) { struct fd_resource* rsrc = (struct fd_resource*)obj; + resource_dtor(env, obj); if (rsrc->fd >= 0) close(rsrc->fd); } -- cgit v1.2.3 From 387ff8e3347d21e9ca5ad3d8c3a694bc79d38bca Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 8 Dec 2016 19:26:14 +0100 Subject: Add stop arguments: fd and is_direct_call --- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 65 +++++++++++++-------------- 1 file changed, 31 insertions(+), 34 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index f6ccd3e6ba..878a9ffda9 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -108,13 +108,14 @@ struct binary_resource { static ErlNifResourceType* fd_resource_type; static void fd_resource_dtor(ErlNifEnv* env, void* obj); -static void fd_resource_stop(ErlNifEnv* env, void* obj); +static void fd_resource_stop(ErlNifEnv* env, void* obj, ErlNifEvent, int); static ErlNifResourceTypeInit fd_rt_init = { fd_resource_dtor, fd_resource_stop }; struct fd_resource { int fd; + int was_selected; }; @@ -1128,10 +1129,6 @@ static ERL_NIF_TERM make_term_string(struct make_term_info* mti, int n) { return enif_make_string(mti->dst_env, "Hello!", ERL_NIF_LATIN1); } -static ERL_NIF_TERM make_term_ref(struct make_term_info* mti, int n) -{ - return enif_make_ref(mti->dst_env); -} static ERL_NIF_TERM make_term_sub_binary(struct make_term_info* mti, int n) { ERL_NIF_TERM orig; @@ -1239,7 +1236,6 @@ static Make_term_Func* make_funcs[] = { make_term_atom, make_term_existing_atom, make_term_string, - //make_term_ref, make_term_sub_binary, make_term_uint, make_term_long, @@ -2032,26 +2028,23 @@ static ERL_NIF_TERM format_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg } -static int get_fd(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifEvent* fd) +static int get_fd(ErlNifEnv* env, ERL_NIF_TERM term, struct fd_resource** rsrc) { - struct fd_resource* rsrc; - - if (!enif_get_resource(env, term, fd_resource_type, (void**)&rsrc)) { + if (!enif_get_resource(env, term, fd_resource_type, (void**)rsrc)) { return 0; } - *fd = rsrc->fd; return 1; } static ERL_NIF_TERM select_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - ErlNifEvent e; + struct fd_resource* fdr; enum ErlNifSelectFlags mode; void* obj; ERL_NIF_TERM ref; int retval; - if (!get_fd(env, argv[0], &e) + if (!get_fd(env, argv[0], &fdr) || !enif_get_uint(env, argv[1], &mode) || !enif_get_resource(env, argv[2], fd_resource_type, &obj)) { @@ -2060,7 +2053,8 @@ static ERL_NIF_TERM select_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv ref = argv[3]; - retval = enif_select(env, e, mode, obj, ref); + fdr->was_selected = 1; + retval = enif_select(env, fdr->fd, mode, obj, ref); return enif_make_int(env, retval); } @@ -2070,7 +2064,6 @@ static ERL_NIF_TERM pipe_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] struct fd_resource* read_rsrc; struct fd_resource* write_rsrc; ERL_NIF_TERM read_fd, write_fd; - unsigned char *inp, *outp; int fds[2], flags; if (pipe(fds) < 0) @@ -2099,16 +2092,16 @@ static ERL_NIF_TERM pipe_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] static ERL_NIF_TERM write_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - ErlNifEvent fd; + struct fd_resource* fdr; ErlNifBinary bin; int n, written = 0; - if (!get_fd(env, argv[0], &fd) + if (!get_fd(env, argv[0], &fdr) || !enif_inspect_binary(env, argv[1], &bin)) return enif_make_badarg(env); for (;;) { - n = write(fd, bin.data + written, bin.size - written); + n = write(fdr->fd, bin.data + written, bin.size - written); if (n >= 0) { written += n; if (written == bin.size) { @@ -2129,19 +2122,19 @@ static ERL_NIF_TERM write_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ static ERL_NIF_TERM read_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - ErlNifEvent fd; + struct fd_resource* fdr; unsigned char* buf; - int n, count, nread = 0; + int n, count; ERL_NIF_TERM res; - if (!get_fd(env, argv[0], &fd) + if (!get_fd(env, argv[0], &fdr) || !enif_get_int(env, argv[1], &count) || count < 1) return enif_make_badarg(env); buf = enif_make_new_binary(env, count, &res); for (;;) { - n = read(fd, buf, count); + n = read(fdr->fd, buf, count); if (n > 0) { if (n < count) { res = enif_make_sub_binary(env, res, 0, n); @@ -2165,29 +2158,33 @@ static ERL_NIF_TERM read_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] static ERL_NIF_TERM is_closed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - ErlNifEvent fd; + struct fd_resource* fdr; - if (!get_fd(env, argv[0], &fd)) + if (!get_fd(env, argv[0], &fdr)) return enif_make_badarg(env); - return fd < 0 ? atom_true : atom_false; + return fdr->fd < 0 ? atom_true : atom_false; } static void fd_resource_dtor(ErlNifEnv* env, void* obj) { - struct fd_resource* rsrc = (struct fd_resource*)obj; + struct fd_resource* fdr = (struct fd_resource*)obj; resource_dtor(env, obj); - if (rsrc->fd >= 0) - close(rsrc->fd); + if (fdr->fd >= 0) { + assert(!fdr->was_selected); + close(fdr->fd); + } } -static void fd_resource_stop(ErlNifEnv* env, void* obj) +static void fd_resource_stop(ErlNifEnv* env, void* obj, ErlNifEvent fd, + int is_direct_call) { - struct fd_resource* rsrc = (struct fd_resource*)obj; - if (rsrc->fd >= 0) { - close(rsrc->fd); - rsrc->fd = -1; /* thread safety ? */ - } + struct fd_resource* fdr = (struct fd_resource*)obj; + assert(fd == fdr->fd); + assert(fd >= 0); + close(fd); + fdr->fd = -1; /* thread safety ? */ + fdr->was_selected = 0; } -- cgit v1.2.3 From 861b276f27952ecbb5a89748b86b7513946617f3 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 16 Dec 2016 16:26:08 +0100 Subject: nif_SUITE: Add last_fd_stop_call --- erts/emulator/test/nif_SUITE.erl | 13 ++++++++++--- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 27 +++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 5 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 2401ff708c..c2429c3405 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -444,7 +444,7 @@ select(Config) when is_list(Config) -> ensure_lib_loaded(Config), Ref = make_ref(), - {R,W} = pipe_nif(), + {{R, R_ptr}, {W, W_ptr}} = pipe_nif(), ok = write_nif(W, <<"hej">>), <<"hej">> = read_nif(R, 3), @@ -472,6 +472,7 @@ select(Config) when is_list(Config) -> eagain = read_nif(R, 1), 0 = select_nif(W,?ERL_NIF_SELECT_STOP,W,Ref), timer:sleep(10), + {1, {W_ptr,_}} = last_fd_stop_call(), true = is_closed_nif(W), [] = flush(), 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,Ref), @@ -480,6 +481,7 @@ select(Config) when is_list(Config) -> 0 = select_nif(R,?ERL_NIF_SELECT_STOP,R,Ref), timer:sleep(10), + {1, {R_ptr,_}} = last_fd_stop_call(), true = is_closed_nif(R), select_2(Config). @@ -490,7 +492,7 @@ select_2(Config) -> Ref1 = make_ref(), Ref2 = make_ref(), - {R,W} = pipe_nif(), + {{R, R_ptr}, {W, W_ptr}} = pipe_nif(), %% Change ref eagain = read_nif(R, 1), @@ -520,9 +522,13 @@ select_2(Config) -> [] = flush(), 0 = select_nif(R,?ERL_NIF_SELECT_STOP,R,Ref1), - 0 = select_nif(W,?ERL_NIF_SELECT_STOP,W,Ref1), timer:sleep(10), + {1, {R_ptr,_}} = last_fd_stop_call(), true = is_closed_nif(R), + + 0 = select_nif(W,?ERL_NIF_SELECT_STOP,W,Ref1), + timer:sleep(10), + {1, {W_ptr,1}} = last_fd_stop_call(), true = is_closed_nif(W), select_3(Config). @@ -2397,6 +2403,7 @@ pipe_nif() -> ?nif_stub. write_nif(_,_) -> ?nif_stub. read_nif(_,_) -> ?nif_stub. is_closed_nif(_) -> ?nif_stub. +last_fd_stop_call() -> ?nif_stub. %% maps is_map_nif(_) -> ?nif_stub. diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 878a9ffda9..813d19ae90 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -2087,7 +2087,9 @@ static ERL_NIF_TERM pipe_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] enif_release_resource(read_rsrc); enif_release_resource(write_rsrc); - return enif_make_tuple2(env, read_fd, write_fd); + return enif_make_tuple2(env, + enif_make_tuple2(env, read_fd, make_pointer(env, read_rsrc)), + enif_make_tuple2(env, write_fd, make_pointer(env, write_rsrc))); } static ERL_NIF_TERM write_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) @@ -2176,17 +2178,37 @@ static void fd_resource_dtor(ErlNifEnv* env, void* obj) } } +static struct { + void* obj; + int was_direct_call; +}last_fd_stop; +int fd_stop_cnt = 0; + static void fd_resource_stop(ErlNifEnv* env, void* obj, ErlNifEvent fd, int is_direct_call) { struct fd_resource* fdr = (struct fd_resource*)obj; assert(fd == fdr->fd); assert(fd >= 0); + + last_fd_stop.obj = obj; + last_fd_stop.was_direct_call = is_direct_call; + fd_stop_cnt++; + close(fd); fdr->fd = -1; /* thread safety ? */ fdr->was_selected = 0; } +static ERL_NIF_TERM last_fd_stop_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ERL_NIF_TERM last, ret; + last = enif_make_tuple2(env, make_pointer(env, last_fd_stop.obj), + enif_make_int(env, last_fd_stop.was_direct_call)); + ret = enif_make_tuple2(env, enif_make_int(env, fd_stop_cnt), last); + fd_stop_cnt = 0; + return ret; +} static ErlNifFunc nif_funcs[] = @@ -2270,7 +2292,8 @@ static ErlNifFunc nif_funcs[] = {"pipe_nif", 0, pipe_nif}, {"write_nif", 2, write_nif}, {"read_nif", 2, read_nif}, - {"is_closed_nif", 1, is_closed_nif} + {"is_closed_nif", 1, is_closed_nif}, + {"last_fd_stop_call", 0, last_fd_stop_call} }; ERL_NIF_INIT(nif_SUITE,nif_funcs,load,NULL,upgrade,unload) -- cgit v1.2.3 From 4c5d33114edea787833d6aa1b0d51ea9d98b3321 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 16 Dec 2016 19:30:22 +0100 Subject: Add ErlNifSelectReturn --- erts/emulator/test/nif_SUITE.erl | 18 +++++++++++++----- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 4 ++-- 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index c2429c3405..8795a3b24a 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -440,6 +440,13 @@ t_on_load(Config) when is_list(Config) -> -define(ERL_NIF_SELECT_WRITE, (1 bsl 1)). -define(ERL_NIF_SELECT_STOP, (1 bsl 2)). +-define(ERL_NIF_SELECT_ERROR, (1 bsl 0)). +-define(ERL_NIF_SELECT_STOP_CALLED, (1 bsl 1)). +-define(ERL_NIF_SELECT_STOP_SCHEDULED, (1 bsl 2)). +-define(ERL_NIF_SELECT_INVALID_EVENT, (1 bsl 3)). +-define(ERL_NIF_SELECT_FAILED, (1 bsl 4)). + + select(Config) when is_list(Config) -> ensure_lib_loaded(Config), @@ -470,7 +477,7 @@ select(Config) when is_list(Config) -> %% Close write and wait for EOF eagain = read_nif(R, 1), - 0 = select_nif(W,?ERL_NIF_SELECT_STOP,W,Ref), + check_stop_ret(select_nif(W,?ERL_NIF_SELECT_STOP,W,Ref)), timer:sleep(10), {1, {W_ptr,_}} = last_fd_stop_call(), true = is_closed_nif(W), @@ -479,7 +486,7 @@ select(Config) when is_list(Config) -> [{select, R, Ref, ready_input}] = flush(), eof = read_nif(R,1), - 0 = select_nif(R,?ERL_NIF_SELECT_STOP,R,Ref), + check_stop_ret(select_nif(R,?ERL_NIF_SELECT_STOP,R,Ref)), timer:sleep(10), {1, {R_ptr,_}} = last_fd_stop_call(), true = is_closed_nif(R), @@ -521,12 +528,12 @@ select_2(Config) -> done = receive_any(), [] = flush(), - 0 = select_nif(R,?ERL_NIF_SELECT_STOP,R,Ref1), + check_stop_ret(select_nif(R,?ERL_NIF_SELECT_STOP,R,Ref1)), timer:sleep(10), {1, {R_ptr,_}} = last_fd_stop_call(), true = is_closed_nif(R), - 0 = select_nif(W,?ERL_NIF_SELECT_STOP,W,Ref1), + ?ERL_NIF_SELECT_STOP_CALLED = select_nif(W,?ERL_NIF_SELECT_STOP,W,Ref1), timer:sleep(10), {1, {W_ptr,1}} = last_fd_stop_call(), true = is_closed_nif(W), @@ -538,7 +545,8 @@ select_3(Config) -> {_,_,2} = last_resource_dtor_call(), ok. - +check_stop_ret(?ERL_NIF_SELECT_STOP_CALLED) -> ok; +check_stop_ret(?ERL_NIF_SELECT_STOP_SCHEDULED) -> ok. write_full(W, C) -> write_full(W, C, <<>>). diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 813d19ae90..d2af081a22 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -2042,7 +2042,7 @@ static ERL_NIF_TERM select_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv enum ErlNifSelectFlags mode; void* obj; ERL_NIF_TERM ref; - int retval; + enum ErlNifSelectReturn retval; if (!get_fd(env, argv[0], &fdr) || !enif_get_uint(env, argv[1], &mode) @@ -2056,7 +2056,7 @@ static ERL_NIF_TERM select_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv fdr->was_selected = 1; retval = enif_select(env, fdr->fd, mode, obj, ref); - return enif_make_int(env, retval); + return enif_make_int(env, (int)retval); } static ERL_NIF_TERM pipe_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From ca7e946af9c2fdc86c1c74259ee7b6881c5aec1e Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Mon, 19 Dec 2016 11:17:05 +0100 Subject: erts: add erlang:system_info(atom_count) --- erts/emulator/test/system_info_SUITE.erl | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl index 3d9e74472b..6a772bf7c9 100644 --- a/erts/emulator/test/system_info_SUITE.erl +++ b/erts/emulator/test/system_info_SUITE.erl @@ -36,7 +36,8 @@ -export([all/0, suite/0]). -export([process_count/1, system_version/1, misc_smoke_tests/1, - heap_size/1, wordsize/1, memory/1, ets_limit/1, atom_limit/1]). + heap_size/1, wordsize/1, memory/1, ets_limit/1, atom_limit/1, + atom_count/1]). suite() -> [{ct_hooks,[ts_install_cth]}, @@ -44,7 +45,7 @@ suite() -> all() -> [process_count, system_version, misc_smoke_tests, - heap_size, wordsize, memory, ets_limit, atom_limit]. + heap_size, wordsize, memory, ets_limit, atom_limit, atom_count]. %%% %%% The test cases ------------------------------------------------------------- @@ -550,3 +551,13 @@ get_atom_limit(Config, AtomsMax) -> end, stop_node(Node), Res. + +%% Verify that system_info(atom_count) works. +atom_count(Config) when is_list(Config) -> + Limit = erlang:system_info(atom_limit), + Count1 = erlang:system_info(atom_count), + list_to_atom(integer_to_list(erlang:unique_integer())), + Count2 = erlang:system_info(atom_count), + true = Limit >= Count2, + true = Count2 > Count1, + ok. -- cgit v1.2.3 From 5621aebf1375fa0e6eb938490c3391300e4efbfe Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 20 Dec 2016 15:45:03 +0100 Subject: erts: Add missing make rules for port_SUITE Seems some default rule made it work before until an upgrade of FreeBSD resulted in: make: don't know how to make dead_port. Stop --- erts/emulator/test/port_SUITE_data/Makefile.src | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/port_SUITE_data/Makefile.src b/erts/emulator/test/port_SUITE_data/Makefile.src index fb7685c4b6..3a343e6d17 100644 --- a/erts/emulator/test/port_SUITE_data/Makefile.src +++ b/erts/emulator/test/port_SUITE_data/Makefile.src @@ -20,6 +20,12 @@ echo_args@exe@: echo_args@obj@ echo_args@obj@: echo_args.c $(CC) -c -o echo_args@obj@ $(CFLAGS) echo_args.c +dead_port@exe@: dead_port@obj@ + $(LD) $(CROSSLDFLAGS) -o dead_port dead_port@obj@ @LIBS@ + +dead_port@obj@: dead_port.c + $(CC) -c -o dead_port@obj@ $(CFLAGS) dead_port.c + port_test.@EMULATOR@: port_test.erl @erl_name@ -compile port_test -- cgit v1.2.3 From eb3e927c110ba8108f2797a23774db14ee70fd76 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 20 Dec 2016 15:46:24 +0100 Subject: erts: Fix some compile warnings for port_SUITE --- erts/emulator/test/port_SUITE_data/port_test.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/port_SUITE_data/port_test.c b/erts/emulator/test/port_SUITE_data/port_test.c index cc3ebdf0f8..e199a0fc13 100644 --- a/erts/emulator/test/port_SUITE_data/port_test.c +++ b/erts/emulator/test/port_SUITE_data/port_test.c @@ -10,6 +10,7 @@ #include #include #include +#include #ifndef __WIN32__ #include @@ -33,7 +34,7 @@ exit(1); \ } -#define MAIN(argc, argv) main(argc, argv) +#define ASSERT(e) ((void) ((e) ? 1 : abort())) extern int errno; @@ -105,9 +106,7 @@ int err; #endif -MAIN(argc, argv) -int argc; -char *argv[]; +int main(int argc, char *argv[]) { int ret, fd_count; if((port_data = (PORT_TEST_DATA *) malloc(sizeof(PORT_TEST_DATA))) == NULL) { @@ -377,9 +376,11 @@ write_reply(buf, size) int size; /* Size of buffer to send. */ { int n; /* Temporary to hold size. */ + int rv; if (port_data->slow_writes <= 0) { /* Normal, "fast", write. */ - write(port_data->fd_to_erl, buf, size); + rv = write(port_data->fd_to_erl, buf, size); + ASSERT(rv == size); } else { /* * Write chunks with delays in between. @@ -387,7 +388,8 @@ write_reply(buf, size) while (size > 0) { n = size > port_data->slow_writes ? port_data->slow_writes : size; - write(port_data->fd_to_erl, buf, n); + rv = write(port_data->fd_to_erl, buf, n); + ASSERT(rv == n); size -= n; buf += n; if (size) @@ -558,7 +560,7 @@ char* spec; /* Specification for reply. */ buf = (char *) malloc(total_size); if (buf == NULL) { fprintf(stderr, "%s: insufficent memory for reply buffer of size %d\n", - port_data->progname, total_size); + port_data->progname, (int)total_size); exit(1); } -- cgit v1.2.3 From 282b0f62f39168c63279e1d4875c3bda43a0366c Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 21 Dec 2016 18:12:14 +0100 Subject: erts: Cleanup and extra assertions in nif_SUITE.c --- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index d2af081a22..d30876433c 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -133,7 +133,6 @@ static ERL_NIF_TERM make_pointer(ErlNifEnv* env, void* p) { void** bin_data; ERL_NIF_TERM res; - ADD_CALL("get_priv_data_ptr"); bin_data = (void**)enif_make_new_binary(env, sizeof(void*), &res); *bin_data = p; return res; @@ -412,8 +411,7 @@ static ERL_NIF_TERM type_test(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ErlNifSInt64 sint64; ErlNifUInt64 uint64; double d; - ERL_NIF_TERM atom, ref1, ref2, term; - size_t len; + ERL_NIF_TERM atom, ref1, ref2; sint = INT_MIN; do { @@ -1047,6 +1045,7 @@ struct make_term_info { ErlNifEnv* caller_env; ErlNifEnv* dst_env; + int dst_env_valid; ERL_NIF_TERM reuse[MAKE_TERM_REUSE_LEN]; unsigned reuse_push; unsigned reuse_pull; @@ -1076,6 +1075,7 @@ static ERL_NIF_TERM pull_term(struct make_term_info* mti) mti->reuse_push < MAKE_TERM_REUSE_LEN) { mti->reuse_pull = 0; if (mti->reuse_push == 0) { + assert(mti->dst_env_valid); mti->reuse[0] = enif_make_list(mti->dst_env, 0); } } @@ -1259,6 +1259,7 @@ static unsigned num_of_make_funcs() static int make_term_n(struct make_term_info* mti, int n, ERL_NIF_TERM* res) { if (n < num_of_make_funcs()) { + assert(mti->dst_env_valid); *res = make_funcs[n](mti, n); push_term(mti, *res); return 1; @@ -1275,6 +1276,7 @@ static ERL_NIF_TERM make_blob(ErlNifEnv* caller_env, ErlNifEnv* dst_env, struct make_term_info mti; mti.caller_env = caller_env; mti.dst_env = dst_env; + mti.dst_env_valid = 1; mti.reuse_push = 0; mti.reuse_pull = 0; mti.resource_type = priv->rt_arr[0].t; @@ -1315,6 +1317,7 @@ static ERL_NIF_TERM alloc_msgenv(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar sizeof(*mti)); mti->caller_env = NULL; mti->dst_env = enif_alloc_env(); + mti->dst_env_valid = 1; mti->reuse_push = 0; mti->reuse_pull = 0; mti->resource_type = priv->rt_arr[0].t; @@ -1346,6 +1349,7 @@ static ERL_NIF_TERM clear_msgenv(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar return enif_make_badarg(env); } enif_clear_env(mti.p->dst_env); + mti.p->dst_env_valid = 1; mti.p->reuse_pull = 0; mti.p->reuse_push = 0; mti.p->blob = enif_make_list(mti.p->dst_env, 0); @@ -1380,6 +1384,8 @@ static ERL_NIF_TERM send_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ } copy = enif_make_copy(env, mti.p->blob); res = enif_send(env, &to, mti.p->dst_env, mti.p->blob); + if (res) + mti.p->dst_env_valid = 0; return enif_make_tuple3(env, atom_ok, enif_make_int(env,res), copy); } @@ -1387,7 +1393,6 @@ static ERL_NIF_TERM send3_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv { mti_t mti; ErlNifPid to; - ERL_NIF_TERM copy; int res; if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp) || !enif_get_local_pid(env, argv[1], &to)) { @@ -1397,6 +1402,8 @@ static ERL_NIF_TERM send3_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv enif_make_copy(mti.p->dst_env, argv[2]), mti.p->blob); res = enif_send(env, &to, mti.p->dst_env, mti.p->blob); + if (res) + mti.p->dst_env_valid = 0; return enif_make_int(env,res); } @@ -1413,6 +1420,8 @@ void* threaded_sender(void *arg) mti.p->send_it = 0; enif_mutex_unlock(mti.p->mtx); mti.p->send_res = enif_send(NULL, &mti.p->to_pid, mti.p->dst_env, mti.p->blob); + if (mti.p->send_res) + mti.p->dst_env_valid = 0; return NULL; } -- cgit v1.2.3 From 4b97d656a9e1774fd4ff984014f085ad661a4fdb Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 21 Dec 2016 18:13:02 +0100 Subject: nif_SUITE: Send message from stop callback --- erts/emulator/test/nif_SUITE.erl | 9 +++++---- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 8795a3b24a..7739a0bc22 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -478,7 +478,7 @@ select(Config) when is_list(Config) -> %% Close write and wait for EOF eagain = read_nif(R, 1), check_stop_ret(select_nif(W,?ERL_NIF_SELECT_STOP,W,Ref)), - timer:sleep(10), + [{fd_resource_stop, W_ptr, _}] = flush(), {1, {W_ptr,_}} = last_fd_stop_call(), true = is_closed_nif(W), [] = flush(), @@ -487,7 +487,7 @@ select(Config) when is_list(Config) -> eof = read_nif(R,1), check_stop_ret(select_nif(R,?ERL_NIF_SELECT_STOP,R,Ref)), - timer:sleep(10), + [{fd_resource_stop, R_ptr, _}] = flush(), {1, {R_ptr,_}} = last_fd_stop_call(), true = is_closed_nif(R), @@ -529,12 +529,13 @@ select_2(Config) -> [] = flush(), check_stop_ret(select_nif(R,?ERL_NIF_SELECT_STOP,R,Ref1)), - timer:sleep(10), + [{fd_resource_stop, R_ptr, _}] = flush(), {1, {R_ptr,_}} = last_fd_stop_call(), true = is_closed_nif(R), + %% Stop without previous read/write select ?ERL_NIF_SELECT_STOP_CALLED = select_nif(W,?ERL_NIF_SELECT_STOP,W,Ref1), - timer:sleep(10), + [{fd_resource_stop, W_ptr, 1}] = flush(), {1, {W_ptr,1}} = last_fd_stop_call(), true = is_closed_nif(W), diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index d30876433c..c4f9611ec8 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -47,6 +47,7 @@ static ERL_NIF_TERM atom_nanosecond; static ERL_NIF_TERM atom_eagain; static ERL_NIF_TERM atom_eof; static ERL_NIF_TERM atom_error; +static ERL_NIF_TERM atom_fd_resource_stop; typedef struct { @@ -116,6 +117,7 @@ static ErlNifResourceTypeInit fd_rt_init = { struct fd_resource { int fd; int was_selected; + ErlNifPid pid; }; @@ -176,6 +178,7 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_eagain = enif_make_atom(env, "eagain"); atom_eof = enif_make_atom(env, "eof"); atom_error = enif_make_atom(env, "error"); + atom_fd_resource_stop = enif_make_atom(env, "fd_resource_stop"); *priv_data = data; return 0; @@ -2063,6 +2066,7 @@ static ERL_NIF_TERM select_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv ref = argv[3]; fdr->was_selected = 1; + enif_self(env, &fdr->pid); retval = enif_select(env, fdr->fd, mode, obj, ref); return enif_make_int(env, (int)retval); @@ -2207,6 +2211,18 @@ static void fd_resource_stop(ErlNifEnv* env, void* obj, ErlNifEvent fd, close(fd); fdr->fd = -1; /* thread safety ? */ fdr->was_selected = 0; + + { + ErlNifEnv* msg_env = enif_alloc_env(); + ERL_NIF_TERM msg; + msg = enif_make_tuple3(msg_env, + atom_fd_resource_stop, + make_pointer(msg_env, obj), + enif_make_int(msg_env, is_direct_call)); + + enif_send(env, &fdr->pid, msg_env, msg); + enif_free_env(msg_env); + } } static ERL_NIF_TERM last_fd_stop_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From a67afb4e2e1e0dda8a8f818c844a2036e703c6f6 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Tue, 10 Jan 2017 16:13:07 +0100 Subject: Fix processes() BIF test cases --- erts/emulator/test/process_SUITE.erl | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index 0f999e0efe..0f492eb982 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -1611,6 +1611,7 @@ spawn_initial_hangarounds(_Cleaner, NP, Max, Len, HAs) when NP > Max -> {Len, HAs}; spawn_initial_hangarounds(Cleaner, NP, Max, Len, HAs) -> Skip = 30, + wait_for_proc_slots(Skip+3), HA1 = spawn_opt(?MODULE, hangaround, [Cleaner, initial_hangaround], [{priority, low}]), HA2 = spawn_opt(?MODULE, hangaround, [Cleaner, initial_hangaround], @@ -1620,6 +1621,15 @@ spawn_initial_hangarounds(Cleaner, NP, Max, Len, HAs) -> spawn_drop(Skip), spawn_initial_hangarounds(Cleaner, NP+Skip, Max, Len+3, [HA1,HA2,HA3|HAs]). +wait_for_proc_slots(MinFreeSlots) -> + case erlang:system_info(process_limit) - erlang:system_info(process_count) of + FreeSlots when FreeSlots < MinFreeSlots -> + receive after 10 -> ok end, + wait_for_proc_slots(MinFreeSlots); + _FreeSlots -> + ok + end. + spawn_drop(N) when N =< 0 -> ok; spawn_drop(N) -> -- cgit v1.2.3 From 6bcdd45abd97134fddfb5b0307b1d256337b0c67 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Wed, 28 Dec 2016 18:23:06 +0100 Subject: Reduction counting on non-tail return --- erts/emulator/test/nif_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 0d3910b2e2..36d512e388 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -1689,7 +1689,7 @@ consume_timeslice(Config) when is_list(Config) -> consume_timeslice_test(Config) when is_list(Config) -> ensure_lib_loaded(Config), - CONTEXT_REDS = 2000, + CONTEXT_REDS = 4000, Me = self(), Go = make_ref(), RedDiff = make_ref(), -- cgit v1.2.3 From 5aff60d96efac96a41b514ed167f13eb787a415f Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Mon, 26 Sep 2016 17:05:50 +0200 Subject: Support for dirty BIFs --- erts/emulator/test/Makefile | 1 + erts/emulator/test/call_trace_SUITE.erl | 2 +- erts/emulator/test/dirty_bif_SUITE.erl | 583 +++++++++++++++++++++ erts/emulator/test/dirty_bif_SUITE_data/.gitignore | 0 erts/emulator/test/old_scheduler_SUITE.erl | 4 +- erts/emulator/test/port_SUITE.erl | 4 +- erts/emulator/test/process_SUITE.erl | 28 +- erts/emulator/test/z_SUITE.erl | 18 +- 8 files changed, 612 insertions(+), 28 deletions(-) create mode 100644 erts/emulator/test/dirty_bif_SUITE.erl create mode 100644 erts/emulator/test/dirty_bif_SUITE_data/.gitignore (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index 2e48c475d5..7c9927c4f3 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -53,6 +53,7 @@ MODULES= \ crypto_SUITE \ ddll_SUITE \ decode_packet_SUITE \ + dirty_bif_SUITE \ dirty_nif_SUITE \ distribution_SUITE \ driver_SUITE \ diff --git a/erts/emulator/test/call_trace_SUITE.erl b/erts/emulator/test/call_trace_SUITE.erl index f7ff04430a..2e303ba9a8 100644 --- a/erts/emulator/test/call_trace_SUITE.erl +++ b/erts/emulator/test/call_trace_SUITE.erl @@ -45,7 +45,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap, {seconds, 30}}]. -all() -> +all() -> Common = [errors, on_load], NotHipe = [process_specs, basic, flags, pam, change_pam, upgrade, diff --git a/erts/emulator/test/dirty_bif_SUITE.erl b/erts/emulator/test/dirty_bif_SUITE.erl new file mode 100644 index 0000000000..01ff8d6efd --- /dev/null +++ b/erts/emulator/test/dirty_bif_SUITE.erl @@ -0,0 +1,583 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010-2014. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +-module(dirty_bif_SUITE). + +%%-define(line_trace,true). +-define(CHECK(Exp,Got), check(Exp,Got,?LINE)). +%%-define(CHECK(Exp,Got), Exp = Got). + +-include_lib("common_test/include/ct.hrl"). + +-export([all/0, suite/0, + init_per_suite/1, end_per_suite/1, + init_per_testcase/2, end_per_testcase/2, + dirty_bif/1, dirty_bif_exception/1, + dirty_bif_multischedule/1, + dirty_bif_multischedule_exception/1, + dirty_scheduler_exit/1, + dirty_call_while_terminated/1, + dirty_heap_access/1, + dirty_process_info/1, + dirty_process_register/1, + dirty_process_trace/1, + code_purge/1]). + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +%% +%% All these tests utilize the debug BIFs: +%% - erts_debug:dirty_cpu/2 - Statically determined +%% to (begin to) execute on a dirty CPU scheduler. +%% - erts_debug:dirty_io/2 - Statically determined +%% to (begin to) execute on a dirty IO scheduler. +%% - erts_debug:dirty/3 +%% Their implementations are located in +%% $ERL_TOP/erts/emulator/beam/beam_debug.c +%% + +all() -> + [dirty_bif, + dirty_bif_multischedule, + dirty_bif_exception, + dirty_bif_multischedule_exception, + dirty_scheduler_exit, + dirty_call_while_terminated, + dirty_heap_access, + dirty_process_info, + dirty_process_register, + dirty_process_trace, + code_purge]. + +init_per_suite(Config) -> + try erlang:system_info(dirty_cpu_schedulers) of + N when is_integer(N), N > 0 -> + Config + catch _:_ -> + {skipped, "No dirty scheduler support"} + end. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(Case, Config) -> + [{testcase, Case} | Config]. + +end_per_testcase(_Case, _Config) -> + ok. + +dirty_bif(Config) when is_list(Config) -> + dirty_cpu = erts_debug:dirty_cpu(scheduler,type), + dirty_io = erts_debug:dirty_io(scheduler,type), + normal = erts_debug:dirty(normal,scheduler,type), + dirty_cpu = erts_debug:dirty(dirty_cpu,scheduler,type), + dirty_io = erts_debug:dirty(dirty_io,scheduler,type), + ok. + +dirty_bif_multischedule(Config) when is_list(Config) -> + ok = erts_debug:dirty_cpu(reschedule,1000), + ok = erts_debug:dirty_io(reschedule,1000), + ok = erts_debug:dirty(normal,reschedule,1000), + ok. + + +dirty_bif_exception(Config) when is_list(Config) -> + lists:foreach(fun (Error) -> + ErrorType = case Error of + _ when is_atom(Error) -> Error; + _ -> badarg + end, + try + erts_debug:dirty_cpu(error, Error), + ct:fail(expected_exception) + catch + error:ErrorType -> + [{erts_debug,dirty_cpu,[error, Error],_}|_] + = erlang:get_stacktrace(), + ok + end, + try + apply(erts_debug,dirty_cpu,[error, Error]), + ct:fail(expected_exception) + catch + error:ErrorType -> + [{erts_debug,dirty_cpu,[error, Error],_}|_] + = erlang:get_stacktrace(), + ok + end, + try + erts_debug:dirty_io(error, Error), + ct:fail(expected_exception) + catch + error:ErrorType -> + [{erts_debug,dirty_io,[error, Error],_}|_] + = erlang:get_stacktrace(), + ok + end, + try + apply(erts_debug,dirty_io,[error, Error]), + ct:fail(expected_exception) + catch + error:ErrorType -> + [{erts_debug,dirty_io,[error, Error],_}|_] + = erlang:get_stacktrace(), + ok + end, + try + erts_debug:dirty(normal, error, Error), + ct:fail(expected_exception) + catch + error:ErrorType -> + [{erts_debug,dirty,[normal, error, Error],_}|_] + = erlang:get_stacktrace(), + ok + end, + try + apply(erts_debug,dirty,[normal, error, Error]), + ct:fail(expected_exception) + catch + error:ErrorType -> + [{erts_debug,dirty,[normal, error, Error],_}|_] + = erlang:get_stacktrace(), + ok + end, + try + erts_debug:dirty(dirty_cpu, error, Error), + ct:fail(expected_exception) + catch + error:ErrorType -> + [{erts_debug,dirty,[dirty_cpu, error, Error],_}|_] + = erlang:get_stacktrace(), + ok + end, + try + apply(erts_debug,dirty,[dirty_cpu, error, Error]), + ct:fail(expected_exception) + catch + error:ErrorType -> + [{erts_debug,dirty,[dirty_cpu, error, Error],_}|_] + = erlang:get_stacktrace(), + ok + end, + try + erts_debug:dirty(dirty_io, error, Error), + ct:fail(expected_exception) + catch + error:ErrorType -> + [{erts_debug,dirty,[dirty_io, error, Error],_}|_] + = erlang:get_stacktrace(), + ok + end, + try + apply(erts_debug,dirty,[dirty_io, error, Error]), + ct:fail(expected_exception) + catch + error:ErrorType -> + [{erts_debug,dirty,[dirty_io, error, Error],_}|_] + = erlang:get_stacktrace(), + ok + end + end, + [badarg, undef, badarith, system_limit, noproc, + make_ref(), {another, "heap", term_to_binary("term")}]), + ok. + + +dirty_bif_multischedule_exception(Config) when is_list(Config) -> + try + erts_debug:dirty_cpu(reschedule,1001) + catch + error:badarg -> + [{erts_debug,dirty_cpu,[reschedule, 1001],_}|_] + = erlang:get_stacktrace(), + ok + end, + try + erts_debug:dirty_io(reschedule,1001) + catch + error:badarg -> + [{erts_debug,dirty_io,[reschedule, 1001],_}|_] + = erlang:get_stacktrace(), + ok + end, + try + erts_debug:dirty(normal,reschedule,1001) + catch + error:badarg -> + [{erts_debug,dirty,[normal,reschedule,1001],_}|_] + = erlang:get_stacktrace(), + ok + end. + +dirty_scheduler_exit(Config) when is_list(Config) -> + {ok, Node} = start_node(Config, "+SDio 1"), + [ok] = mcall(Node, + [fun() -> + Start = erlang:monotonic_time(millisecond), + ok = test_dirty_scheduler_exit(), + End = erlang:monotonic_time(millisecond), + io:format("Time=~p ms~n", [End-Start]), + ok + end]), + stop_node(Node), + ok. + +test_dirty_scheduler_exit() -> + process_flag(trap_exit,true), + test_dse(10,[]). +test_dse(0,Pids) -> + timer:sleep(100), + kill_dse(Pids,[]); +test_dse(N,Pids) -> + Pid = spawn_link(fun () -> erts_debug:dirty_io(wait, 5000) end), + test_dse(N-1,[Pid|Pids]). + +kill_dse([],Killed) -> + wait_dse(Killed); +kill_dse([Pid|Pids],AlreadyKilled) -> + exit(Pid,kill), + kill_dse(Pids,[Pid|AlreadyKilled]). + +wait_dse([]) -> + ok; +wait_dse([Pid|Pids]) -> + receive + {'EXIT',Pid,Reason} -> + killed = Reason + end, + wait_dse(Pids). + +dirty_call_while_terminated(Config) when is_list(Config) -> + Me = self(), + Bin = list_to_binary(lists:duplicate(4711, $r)), + {value, {BinAddr, 4711, 1}} = lists:keysearch(4711, 2, + element(2, + process_info(self(), + binary))), + {Dirty, DM} = spawn_opt(fun () -> + erts_debug:dirty_cpu(alive_waitexiting, Me), + blipp:blupp(Bin) + end, + [monitor,link]), + receive {alive, Dirty} -> ok end, + {value, {BinAddr, 4711, 2}} = lists:keysearch(4711, 2, + element(2, + process_info(self(), + binary))), + Reason = die_dirty_process, + OT = process_flag(trap_exit, true), + exit(Dirty, Reason), + receive + {'DOWN', DM, process, Dirty, R0} -> + R0 = Reason + end, + receive + {'EXIT', Dirty, R1} -> + R1 = Reason + end, + undefined = process_info(Dirty), + undefined = process_info(Dirty, status), + false = erlang:is_process_alive(Dirty), + false = lists:member(Dirty, processes()), + %% Binary still refered by Dirty process not yet cleaned up + %% since the dirty bif has not yet returned... + {value, {BinAddr, 4711, 2}} = lists:keysearch(4711, 2, + element(2, + process_info(self(), + binary))), + receive after 2000 -> ok end, + receive + Msg -> + ct:fail({unexpected_message, Msg}) + after + 0 -> + ok + end, + {value, {BinAddr, 4711, 1}} = lists:keysearch(4711, 2, + element(2, + process_info(self(), + binary))), + process_flag(trap_exit, OT), + try + blipp:blupp(Bin) + catch + _ : _ -> ok + end. + +dirty_heap_access(Config) when is_list(Config) -> + {ok, Node} = start_node(Config), + Me = self(), + RGL = rpc:call(Node,erlang,whereis,[init]), + Ref = rpc:call(Node,erlang,make_ref,[]), + Dirty = spawn_link(fun () -> + Res = erts_debug:dirty_cpu(copy, Ref), + garbage_collect(), + Me ! {self(), Res}, + receive after infinity -> ok end + end), + {N, R} = access_dirty_heap(Dirty, RGL, 0, 0), + receive + {_Pid, Res} -> + 1000 = length(Res), + lists:foreach(fun (X) -> Ref = X end, Res) + end, + unlink(Dirty), + exit(Dirty, kill), + stop_node(Node), + {comment, integer_to_list(N) ++ " GL change loops; " + ++ integer_to_list(R) ++ " while running dirty"}. + +access_dirty_heap(Dirty, RGL, N, R) -> + case process_info(Dirty, status) of + {status, waiting} -> + {N, R}; + {status, Status} -> + {group_leader, GL} = process_info(Dirty, group_leader), + true = group_leader(RGL, Dirty), + {group_leader, RGL} = process_info(Dirty, group_leader), + true = group_leader(GL, Dirty), + {group_leader, GL} = process_info(Dirty, group_leader), + access_dirty_heap(Dirty, RGL, N+1, case Status of + running -> + R+1; + _ -> + R + end) + end. + +%% These tests verify that processes that access a process executing a +%% dirty BIF where the main lock is needed for that access do not get +%% blocked. Each test passes its pid to dirty_sleeper, which sends an +%% 'alive' message when it's running on a dirty scheduler and just before +%% it starts a 6 second sleep. When it receives the message, it verifies +%% that access to the dirty process is as it expects. After the dirty +%% process finishes its 6 second sleep but before it returns from the dirty +%% scheduler, it sends a 'done' message. If the tester already received +%% that message, the test fails because it means attempting to access the +%% dirty process waited for that process to return to a regular scheduler, +%% so verify that we haven't received that message, and also verify that +%% the dirty process is still alive immediately after accessing it. +dirty_process_info(Config) when is_list(Config) -> + access_dirty_process( + Config, + fun() -> ok end, + fun(BifPid) -> + PI = process_info(BifPid), + {current_function,{erts_debug,dirty_io,2}} = + lists:keyfind(current_function, 1, PI), + ok + end, + fun(_) -> ok end). + +dirty_process_register(Config) when is_list(Config) -> + access_dirty_process( + Config, + fun() -> ok end, + fun(BifPid) -> + register(test_dirty_process_register, BifPid), + BifPid = whereis(test_dirty_process_register), + unregister(test_dirty_process_register), + false = lists:member(test_dirty_process_register, + registered()), + ok + end, + fun(_) -> ok end). + +dirty_process_trace(Config) when is_list(Config) -> + access_dirty_process( + Config, + fun() -> + erlang:trace_pattern({erts_debug,dirty_io,2}, + [{'_',[],[{return_trace}]}], + [local,meta]), + ok + end, + fun(BifPid) -> + erlang:trace(BifPid, true, [call,timestamp]), + ok + end, + fun(BifPid) -> + receive + {done, BifPid} -> + receive + {trace_ts,BifPid,call,{erts_debug,dirty_io,_},_} -> + ok + after + 0 -> + error(missing_trace_call_message) + end %%, + %% receive + %% {trace_ts,BifPid,return_from,{erts_debug,dirty_io,2}, + %% ok,_} -> + %% ok + %% after + %% 100 -> + %% error(missing_trace_return_message) + %% end + after + 6500 -> + error(missing_done_message) + end, + ok + end). + +dirty_code_test_code() -> + " +-module(dirty_code_test). + +-export([func/1]). + +func(Fun) -> + Fun(), + blipp:blapp(). + +". + +code_purge(Config) when is_list(Config) -> + Path = ?config(data_dir, Config), + File = filename:join(Path, "dirty_code_test.erl"), + ok = file:write_file(File, dirty_code_test_code()), + {ok, dirty_code_test, Bin} = compile:file(File, [binary]), + {module, dirty_code_test} = erlang:load_module(dirty_code_test, Bin), + Start = erlang:monotonic_time(), + {Pid1, Mon1} = spawn_monitor(fun () -> + dirty_code_test:func(fun () -> + %% Sleep for 6 seconds + %% in dirty bif... + erts_debug:dirty_io(wait,6000) + end) + end), + {module, dirty_code_test} = erlang:load_module(dirty_code_test, Bin), + {Pid2, Mon2} = spawn_monitor(fun () -> + dirty_code_test:func(fun () -> + %% Sleep for 6 seconds + %% in dirty bif... + erts_debug:dirty_io(wait,6000) + end) + end), + receive + {'DOWN', Mon1, process, Pid1, _} -> + ct:fail(premature_death) + after 100 -> + ok + end, + true = erlang:purge_module(dirty_code_test), + receive + {'DOWN', Mon1, process, Pid1, Reason1} -> + killed = Reason1 + end, + receive + {'DOWN', Mon2, process, Pid2, _} -> + ct:fail(premature_death) + after 100 -> + ok + end, + true = erlang:delete_module(dirty_code_test), + receive + {'DOWN', Mon2, process, Pid2, _} -> + ct:fail(premature_death) + after 100 -> + ok + end, + true = erlang:purge_module(dirty_code_test), + receive + {'DOWN', Mon2, process, Pid2, Reason2} -> + killed = Reason2 + end, + End = erlang:monotonic_time(), + Time = erlang:convert_time_unit(End-Start, native, milli_seconds), + io:format("Time=~p~n", [Time]), + true = Time =< 1000, + ok. + +%% +%% Internal... +%% + +access_dirty_process(Config, Start, Test, Finish) -> + {ok, Node} = start_node(Config, ""), + [ok] = mcall(Node, + [fun() -> + ok = test_dirty_process_access(Start, Test, Finish) + end]), + stop_node(Node), + ok. + +test_dirty_process_access(Start, Test, Finish) -> + ok = Start(), + Self = self(), + BifPid = spawn_link(fun() -> + ok = erts_debug:dirty_io(ready_wait6_done, Self) + end), + ok = receive + {ready, BifPid} -> + ok = Test(BifPid), + receive + {done, BifPid} -> + error(dirty_process_info_blocked) + after + 0 -> + true = erlang:is_process_alive(BifPid), + ok + end + after + 3000 -> + error(timeout) + end, + ok = Finish(BifPid). + +receive_any() -> + receive M -> M end. + +start_node(Config) -> + start_node(Config, ""). + +start_node(Config, Args) when is_list(Config) -> + Pa = filename:dirname(code:which(?MODULE)), + Name = list_to_atom(atom_to_list(?MODULE) + ++ "-" + ++ atom_to_list(proplists:get_value(testcase, Config)) + ++ "-" + ++ integer_to_list(erlang:system_time(second)) + ++ "-" + ++ integer_to_list(erlang:unique_integer([positive]))), + test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]). + +stop_node(Node) -> + test_server:stop_node(Node). + +mcall(Node, Funs) -> + Parent = self(), + Refs = lists:map(fun (Fun) -> + Ref = make_ref(), + spawn_link(Node, + fun () -> + Res = Fun(), + unlink(Parent), + Parent ! {Ref, Res} + end), + Ref + end, Funs), + lists:map(fun (Ref) -> + receive + {Ref, Res} -> + Res + end + end, Refs). diff --git a/erts/emulator/test/dirty_bif_SUITE_data/.gitignore b/erts/emulator/test/dirty_bif_SUITE_data/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erts/emulator/test/old_scheduler_SUITE.erl b/erts/emulator/test/old_scheduler_SUITE.erl index ffe7d40139..8515a87df8 100644 --- a/erts/emulator/test/old_scheduler_SUITE.erl +++ b/erts/emulator/test/old_scheduler_SUITE.erl @@ -64,11 +64,11 @@ all() -> init_per_testcase(_Case, Config) -> %% main test process needs max prio Prio = process_flag(priority, max), - MS = erlang:system_flag(multi_scheduling, block), + MS = erlang:system_flag(multi_scheduling, block_normal), [{prio,Prio},{multi_scheduling, MS}|Config]. end_per_testcase(_Case, Config) -> - erlang:system_flag(multi_scheduling, unblock), + erlang:system_flag(multi_scheduling, unblock_normal), Prio=proplists:get_value(prio, Config), process_flag(priority, Prio), ok. diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index 23594aa8c4..2a13b2d2f4 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -2066,13 +2066,13 @@ exit_status_msb_test(Config, SleepSecs) when is_list(Config) -> StartedTime = (erlang:monotonic_time(microsecond) - Start)/1000000, io:format("StartedTime = ~p~n", [StartedTime]), true = StartedTime < SleepSecs, - erlang:system_flag(multi_scheduling, block), + erlang:system_flag(multi_scheduling, block_normal), lists:foreach(fun (P) -> receive {P, done} -> ok end end, Procs), DoneTime = (erlang:monotonic_time(microsecond) - Start)/1000000, io:format("DoneTime = ~p~n", [DoneTime]), true = DoneTime > SleepSecs, ok = verify_multi_scheduling_blocked(), - erlang:system_flag(multi_scheduling, unblock), + erlang:system_flag(multi_scheduling, unblock_normal), case {length(lists:usort(lists:flatten(SIds))), NoSchedsOnln} of {N, N} -> ok; diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index 5712c9fa74..e14185e881 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -1028,9 +1028,9 @@ low_prio(Config) when is_list(Config) -> 1 -> ok = low_prio_test(Config); _ -> - erlang:system_flag(multi_scheduling, block), + erlang:system_flag(multi_scheduling, block_normal), ok = low_prio_test(Config), - erlang:system_flag(multi_scheduling, unblock), + erlang:system_flag(multi_scheduling, unblock_normal), {comment, "Test not written for SMP runtime system. " "Multi scheduling blocked during test."} @@ -1097,9 +1097,9 @@ yield(Config) when is_list(Config) -> ++ ") is enabled. Testcase gets messed up by modfied " "timing."}; _ -> - MS = erlang:system_flag(multi_scheduling, block), + MS = erlang:system_flag(multi_scheduling, block_normal), yield_test(), - erlang:system_flag(multi_scheduling, unblock), + erlang:system_flag(multi_scheduling, unblock_normal), case MS of blocked -> {comment, @@ -1679,7 +1679,7 @@ processes_bif_test() -> true -> %% Do it again with a process suspended while %% in the processes/0 bif. - erlang:system_flag(multi_scheduling, block), + erlang:system_flag(multi_scheduling, block_normal), Suspendee = spawn_link(fun () -> Tester ! {suspend_me, self()}, Tester ! {self(), @@ -1692,7 +1692,7 @@ processes_bif_test() -> end), receive {suspend_me, Suspendee} -> ok end, erlang:suspend_process(Suspendee), - erlang:system_flag(multi_scheduling, unblock), + erlang:system_flag(multi_scheduling, unblock_normal), [{status,suspended},{current_function,{erlang,ptab_list_continue,2}}] = process_info(Suspendee, [status, current_function]), @@ -1732,10 +1732,10 @@ do_processes_bif_test(WantReds, DieTest, Processes) -> Splt = NoTestProcs div 10, {TP1, TP23} = lists:split(Splt, TestProcs), {TP2, TP3} = lists:split(Splt, TP23), - erlang:system_flag(multi_scheduling, block), + erlang:system_flag(multi_scheduling, block_normal), Tester ! DoIt, receive GetGoing -> ok end, - erlang:system_flag(multi_scheduling, unblock), + erlang:system_flag(multi_scheduling, unblock_normal), SpawnProcesses(high), lists:foreach( fun (P) -> SpawnHangAround(), @@ -1944,7 +1944,7 @@ processes_gc_trap(Config) when is_list(Config) -> processes() end, - erlang:system_flag(multi_scheduling, block), + erlang:system_flag(multi_scheduling, block_normal), Suspendee = spawn_link(fun () -> Tester ! {suspend_me, self()}, Tester ! {self(), @@ -1954,7 +1954,7 @@ processes_gc_trap(Config) when is_list(Config) -> end), receive {suspend_me, Suspendee} -> ok end, erlang:suspend_process(Suspendee), - erlang:system_flag(multi_scheduling, unblock), + erlang:system_flag(multi_scheduling, unblock_normal), [{status,suspended}, {current_function,{erlang,ptab_list_continue,2}}] = process_info(Suspendee, [status, current_function]), @@ -2161,7 +2161,7 @@ processes_term_proc_list_test(MustChk) -> end) end, SpawnSuspendProcessesProc = fun () -> - erlang:system_flag(multi_scheduling, block), + erlang:system_flag(multi_scheduling, block_normal), P = spawn_link(fun () -> Tester ! {suspend_me, self()}, Tester ! {self(), @@ -2171,7 +2171,7 @@ processes_term_proc_list_test(MustChk) -> end), receive {suspend_me, P} -> ok end, erlang:suspend_process(P), - erlang:system_flag(multi_scheduling, unblock), + erlang:system_flag(multi_scheduling, unblock_normal), [{status,suspended}, {current_function,{erlang,ptab_list_continue,2}}] = process_info(P, [status, current_function]), @@ -2232,7 +2232,7 @@ processes_term_proc_list_test(MustChk) -> S8 = SpawnSuspendProcessesProc(), ?CHK_TERM_PROC_LIST(MustChk, 7), - erlang:system_flag(multi_scheduling, block), + erlang:system_flag(multi_scheduling, block_normal), Exit(S8), ?CHK_TERM_PROC_LIST(MustChk, 7), Exit(S5), @@ -2241,7 +2241,7 @@ processes_term_proc_list_test(MustChk) -> ?CHK_TERM_PROC_LIST(MustChk, 6), Exit(S6), ?CHK_TERM_PROC_LIST(MustChk, 0), - erlang:system_flag(multi_scheduling, unblock), + erlang:system_flag(multi_scheduling, unblock_normal), as_expected. diff --git a/erts/emulator/test/z_SUITE.erl b/erts/emulator/test/z_SUITE.erl index ab56018373..d663cc548c 100644 --- a/erts/emulator/test/z_SUITE.erl +++ b/erts/emulator/test/z_SUITE.erl @@ -68,8 +68,8 @@ schedulers_alive(Config) when is_list(Config) -> enabled -> io:format("Testing blocking process exit~n"), BF = fun () -> - blocked = erlang:system_flag(multi_scheduling, - block), + blocked_normal = erlang:system_flag(multi_scheduling, + block_normal), Master ! {self(), blocking}, receive after infinity -> ok end end, @@ -77,21 +77,21 @@ schedulers_alive(Config) when is_list(Config) -> Mon = erlang:monitor(process, Blocker), receive {Blocker, blocking} -> ok end, [Blocker] - = erlang:system_info(multi_scheduling_blockers), + = erlang:system_info(normal_multi_scheduling_blockers), unlink(Blocker), exit(Blocker, kill), receive {'DOWN', Mon, _, _, _} -> ok end, enabled = erlang:system_info(multi_scheduling), - [] = erlang:system_info(multi_scheduling_blockers), + [] = erlang:system_info(normal_multi_scheduling_blockers), ok end, io:format("Testing blocked~n"), - erlang:system_flag(multi_scheduling, block), + erlang:system_flag(multi_scheduling, block_normal), case erlang:system_info(multi_scheduling) of enabled -> ct:fail(multi_scheduling_enabled); - blocked -> - [Master] = erlang:system_info(multi_scheduling_blockers); + blocked_normal -> + [Master] = erlang:system_info(normal_multi_scheduling_blockers); disabled -> ok end, Ps = lists:map( @@ -109,8 +109,8 @@ schedulers_alive(Config) when is_list(Config) -> unlink(P), exit(P, bang) end, Ps), - case erlang:system_flag(multi_scheduling, unblock) of - blocked -> ct:fail(multi_scheduling_blocked); + case erlang:system_flag(multi_scheduling, unblock_normal) of + blocked_normal -> ct:fail(multi_scheduling_blocked); disabled -> ok; enabled -> ok end, -- cgit v1.2.3 From 1239d92556cc0a7921648cbd4abd9f9a397b29b8 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 21 Dec 2016 18:12:14 +0100 Subject: erts: Cleanup and extra assertions in nif_SUITE.c --- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 2c93891852..4decb7f418 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -116,7 +116,6 @@ static ERL_NIF_TERM make_pointer(ErlNifEnv* env, void* p) { void** bin_data; ERL_NIF_TERM res; - ADD_CALL("get_priv_data_ptr"); bin_data = (void**)enif_make_new_binary(env, sizeof(void*), &res); *bin_data = p; return res; @@ -389,8 +388,7 @@ static ERL_NIF_TERM type_test(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ ErlNifSInt64 sint64; ErlNifUInt64 uint64; double d; - ERL_NIF_TERM atom, ref1, ref2, term; - size_t len; + ERL_NIF_TERM atom, ref1, ref2; sint = INT_MIN; do { @@ -1024,6 +1022,7 @@ struct make_term_info { ErlNifEnv* caller_env; ErlNifEnv* dst_env; + int dst_env_valid; ERL_NIF_TERM reuse[MAKE_TERM_REUSE_LEN]; unsigned reuse_push; unsigned reuse_pull; @@ -1053,6 +1052,7 @@ static ERL_NIF_TERM pull_term(struct make_term_info* mti) mti->reuse_push < MAKE_TERM_REUSE_LEN) { mti->reuse_pull = 0; if (mti->reuse_push == 0) { + assert(mti->dst_env_valid); mti->reuse[0] = enif_make_list(mti->dst_env, 0); } } @@ -1241,6 +1241,7 @@ static unsigned num_of_make_funcs() static int make_term_n(struct make_term_info* mti, int n, ERL_NIF_TERM* res) { if (n < num_of_make_funcs()) { + assert(mti->dst_env_valid); *res = make_funcs[n](mti, n); push_term(mti, *res); return 1; @@ -1257,6 +1258,7 @@ static ERL_NIF_TERM make_blob(ErlNifEnv* caller_env, ErlNifEnv* dst_env, struct make_term_info mti; mti.caller_env = caller_env; mti.dst_env = dst_env; + mti.dst_env_valid = 1; mti.reuse_push = 0; mti.reuse_pull = 0; mti.resource_type = priv->rt_arr[0].t; @@ -1297,6 +1299,7 @@ static ERL_NIF_TERM alloc_msgenv(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar sizeof(*mti)); mti->caller_env = NULL; mti->dst_env = enif_alloc_env(); + mti->dst_env_valid = 1; mti->reuse_push = 0; mti->reuse_pull = 0; mti->resource_type = priv->rt_arr[0].t; @@ -1328,6 +1331,7 @@ static ERL_NIF_TERM clear_msgenv(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar return enif_make_badarg(env); } enif_clear_env(mti.p->dst_env); + mti.p->dst_env_valid = 1; mti.p->reuse_pull = 0; mti.p->reuse_push = 0; mti.p->blob = enif_make_list(mti.p->dst_env, 0); @@ -1362,6 +1366,8 @@ static ERL_NIF_TERM send_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ } copy = enif_make_copy(env, mti.p->blob); res = enif_send(env, &to, mti.p->dst_env, mti.p->blob); + if (res) + mti.p->dst_env_valid = 0; return enif_make_tuple3(env, atom_ok, enif_make_int(env,res), copy); } @@ -1369,7 +1375,6 @@ static ERL_NIF_TERM send3_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv { mti_t mti; ErlNifPid to; - ERL_NIF_TERM copy; int res; if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp) || !enif_get_local_pid(env, argv[1], &to)) { @@ -1379,6 +1384,8 @@ static ERL_NIF_TERM send3_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv enif_make_copy(mti.p->dst_env, argv[2]), mti.p->blob); res = enif_send(env, &to, mti.p->dst_env, mti.p->blob); + if (res) + mti.p->dst_env_valid = 0; return enif_make_int(env,res); } @@ -1395,6 +1402,8 @@ void* threaded_sender(void *arg) mti.p->send_it = 0; enif_mutex_unlock(mti.p->mtx); mti.p->send_res = enif_send(NULL, &mti.p->to_pid, mti.p->dst_env, mti.p->blob); + if (mti.p->send_res) + mti.p->dst_env_valid = 0; return NULL; } -- cgit v1.2.3 From 82ba60f0ead61f344e2a7ebd383f62e99cb0375d Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 16 Jan 2017 18:01:20 +0100 Subject: erts: Fix port_trace_SUITE to join threads when port is closed before driver may be unloaded. --- .../emulator/test/port_trace_SUITE_data/echo_drv.c | 39 ++++++++++++++++------ 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/port_trace_SUITE_data/echo_drv.c b/erts/emulator/test/port_trace_SUITE_data/echo_drv.c index b545523192..20ec33a594 100644 --- a/erts/emulator/test/port_trace_SUITE_data/echo_drv.c +++ b/erts/emulator/test/port_trace_SUITE_data/echo_drv.c @@ -2,23 +2,30 @@ #include "erl_driver.h" #include #include +#include /* ------------------------------------------------------------------------- ** Data types **/ +struct my_thread { + struct my_thread* next; + ErlDrvTid tid; +}; typedef struct _erl_drv_data { ErlDrvPort erlang_port; ErlDrvTermData caller; + struct my_thread* threads; } EchoDrvData; struct remote_send_term { - char *buf; - int len; + struct my_thread thread; ErlDrvTermData port; ErlDrvTermData caller; + int len; + char buf[1]; /* buf[len] */ }; #define ECHO_DRV_NOOP 0 @@ -86,7 +93,7 @@ static ErlDrvEntry echo_drv_entry = { NULL }; -static void send_term_thread(void *); +static void* send_term_thread(void *); /* ------------------------------------------------------------------------- ** Entry functions @@ -111,10 +118,22 @@ static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command) EchoDrvData *echo_drv_data_p = driver_alloc(sizeof(EchoDrvData)); echo_drv_data_p->erlang_port = port; echo_drv_data_p->caller = driver_caller(port); + echo_drv_data_p->threads = NULL; return echo_drv_data_p; } -static void echo_drv_stop(EchoDrvData *data_p) { +static void echo_drv_stop(EchoDrvData *data_p) +{ + struct my_thread* thr = data_p->threads; + + while (thr) { + struct my_thread* next = thr->next; + void* exit_value; + int ret = erl_drv_thread_join(thr->tid, &exit_value); + assert(ret == 0 && exit_value == NULL); + driver_free(thr); + thr = next; + } driver_free(data_p); } @@ -212,14 +231,14 @@ static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { } case ECHO_DRV_REMOTE_SEND_TERM: { - ErlDrvTid tid; - struct remote_send_term *t = malloc(sizeof(struct remote_send_term)); + struct remote_send_term *t = driver_alloc(sizeof(struct remote_send_term) + len); t->len = len-1; - t->buf = malloc(len-1); t->port = driver_mk_port(port); t->caller = data_p->caller; memcpy(t->buf, buf+1, t->len); - erl_drv_thread_create("tmp_thread", &tid, send_term_thread, t, NULL); + erl_drv_thread_create("tmp_thread", &t->thread.tid, send_term_thread, t, NULL); + t->thread.next = data_p->threads; + data_p->threads = &t->thread; break; } case ECHO_DRV_SAVE_CALLER: @@ -262,7 +281,7 @@ static ErlDrvSSizeT echo_drv_call(ErlDrvData drv_data, return len-command; } -static void send_term_thread(void *a) +static void* send_term_thread(void *a) { struct remote_send_term *t = (struct remote_send_term*)a; ErlDrvTermData term[] = { @@ -273,5 +292,5 @@ static void send_term_thread(void *a) ERL_DRV_TUPLE, 3}; erl_drv_send_term(t->port, t->caller, term, sizeof(term) / sizeof(ErlDrvTermData)); - return; + return NULL; } -- cgit v1.2.3 From fd1fb9070333fe5b91f4528841a4b0fe71bbf096 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Thu, 12 Jan 2017 14:25:30 +0100 Subject: Always return info from system_info(dirty_[cpu|io]_schedulers*) --- erts/emulator/test/dirty_bif_SUITE.erl | 8 ++++---- erts/emulator/test/dirty_nif_SUITE.erl | 8 ++++---- erts/emulator/test/scheduler_SUITE.erl | 22 ++++++++-------------- 3 files changed, 16 insertions(+), 22 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/dirty_bif_SUITE.erl b/erts/emulator/test/dirty_bif_SUITE.erl index 01ff8d6efd..308323594d 100644 --- a/erts/emulator/test/dirty_bif_SUITE.erl +++ b/erts/emulator/test/dirty_bif_SUITE.erl @@ -67,10 +67,10 @@ all() -> code_purge]. init_per_suite(Config) -> - try erlang:system_info(dirty_cpu_schedulers) of - N when is_integer(N), N > 0 -> - Config - catch _:_ -> + case erlang:system_info(dirty_cpu_schedulers) of + N when N > 0 -> + Config; + _ -> {skipped, "No dirty scheduler support"} end. diff --git a/erts/emulator/test/dirty_nif_SUITE.erl b/erts/emulator/test/dirty_nif_SUITE.erl index a61fd92a18..991ba0acc8 100644 --- a/erts/emulator/test/dirty_nif_SUITE.erl +++ b/erts/emulator/test/dirty_nif_SUITE.erl @@ -54,8 +54,8 @@ all() -> dirty_nif_send_traced]. init_per_suite(Config) -> - try erlang:system_info(dirty_cpu_schedulers) of - N when is_integer(N), N > 0 -> + case erlang:system_info(dirty_cpu_schedulers) of + N when N > 0 -> case lib_loaded() of false -> ok = erlang:load_nif( @@ -64,8 +64,8 @@ init_per_suite(Config) -> true -> ok end, - Config - catch _:_ -> + Config; + _ -> {skipped, "No dirty scheduler support"} end. diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl index 3aee15a8fc..b178dede5b 100644 --- a/erts/emulator/test/scheduler_SUITE.erl +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -1095,16 +1095,13 @@ scheduler_threads(Config) when is_list(Config) -> end. dirty_scheduler_threads(Config) when is_list(Config) -> - SmpSupport = erlang:system_info(smp_support), - try - erlang:system_info(dirty_cpu_schedulers), - dirty_scheduler_threads_test(Config, SmpSupport) - catch - error:badarg -> - {skipped, "No dirty scheduler support"} + case erlang:system_info(dirty_cpu_schedulers) of + 0 -> {skipped, "No dirty scheduler support"}; + _ -> dirty_scheduler_threads_test(Config) end. -dirty_scheduler_threads_test(Config, SmpSupport) -> +dirty_scheduler_threads_test(Config) -> + SmpSupport = erlang:system_info(smp_support), {Sched, SchedOnln, _} = get_dsstate(Config, ""), {HalfSched, HalfSchedOnln} = case SmpSupport of false -> {1,1}; @@ -1374,12 +1371,9 @@ sst2_loop(N) -> sst2_loop(N-1). sst3_loop(S, N) -> - try erlang:system_info(dirty_cpu_schedulers) of - DS -> - sst3_loop_with_dirty_schedulers(S, DS, N) - catch - error:badarg -> - sst3_loop_normal_schedulers_only(S, N) + case erlang:system_info(dirty_cpu_schedulers) of + 0 -> sst3_loop_normal_schedulers_only(S, N); + DS -> sst3_loop_with_dirty_schedulers(S, DS, N) end. sst3_loop_normal_schedulers_only(_S, 0) -> -- cgit v1.2.3 From f9459092940943876dff040ee997515b96fd5d50 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Wed, 4 Jan 2017 18:10:26 +0100 Subject: Scheduler wall time support for dirty schedulers --- erts/emulator/test/statistics_SUITE.erl | 131 ++++++++++++++++++++++++++++---- 1 file changed, 118 insertions(+), 13 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/statistics_SUITE.erl b/erts/emulator/test/statistics_SUITE.erl index a1f12ba93c..f51244485b 100644 --- a/erts/emulator/test/statistics_SUITE.erl +++ b/erts/emulator/test/statistics_SUITE.erl @@ -28,6 +28,8 @@ runtime_update/1, runtime_diff/1, run_queue_one/1, scheduler_wall_time/1, + scheduler_wall_time_all/1, + msb_scheduler_wall_time/1, reductions/1, reductions_big/1, garbage_collection/1, io/1, badarg/1, run_queues_lengths_active_tasks/1, msacc/1]). @@ -43,7 +45,9 @@ suite() -> all() -> [{group, wall_clock}, {group, runtime}, reductions, - reductions_big, {group, run_queue}, scheduler_wall_time, + reductions_big, {group, run_queue}, + scheduler_wall_time, scheduler_wall_time_all, + msb_scheduler_wall_time, garbage_collection, io, badarg, run_queues_lengths_active_tasks, msacc]. @@ -271,35 +275,64 @@ hog_iter(0, Mon) -> %% Tests that statistics(scheduler_wall_time) works as intended scheduler_wall_time(Config) when is_list(Config) -> + scheduler_wall_time_test(scheduler_wall_time). + +%% Tests that statistics(scheduler_wall_time_all) works as intended +scheduler_wall_time_all(Config) when is_list(Config) -> + scheduler_wall_time_test(scheduler_wall_time_all). + +scheduler_wall_time_test(Type) -> %% Should return undefined if system_flag is not turned on yet - undefined = statistics(scheduler_wall_time), + undefined = statistics(Type), %% Turn on statistics false = erlang:system_flag(scheduler_wall_time, true), try Schedulers = erlang:system_info(schedulers_online), + DirtyCPUSchedulers = erlang:system_info(dirty_cpu_schedulers_online), + DirtyIOSchedulers = erlang:system_info(dirty_io_schedulers), + TotLoadSchedulers = case Type of + scheduler_wall_time_all -> + Schedulers + DirtyCPUSchedulers + DirtyIOSchedulers; + scheduler_wall_time -> + Schedulers + DirtyCPUSchedulers + end, + %% Let testserver and everyone else finish their work timer:sleep(1500), %% Empty load - EmptyLoad = get_load(), + EmptyLoad = get_load(Type), {false, _} = {lists:any(fun(Load) -> Load > 50 end, EmptyLoad),EmptyLoad}, MeMySelfAndI = self(), StartHog = fun() -> - Pid = spawn(?MODULE, hog, [self()]), + Pid = spawn_link(?MODULE, hog, [self()]), receive hog_started -> MeMySelfAndI ! go end, Pid end, + StartDirtyHog = fun(Func) -> + F = fun () -> + erts_debug:Func(alive_waitexiting, + MeMySelfAndI) + end, + Pid = spawn_link(F), + receive {alive, Pid} -> ok end, + Pid + end, P1 = StartHog(), %% Max on one, the other schedulers empty (hopefully) %% Be generous the process can jump between schedulers %% which is ok and we don't want the test to fail for wrong reasons - _L1 = [S1Load|EmptyScheds1] = get_load(), + _L1 = [S1Load|EmptyScheds1] = get_load(Type), {true,_} = {S1Load > 50,S1Load}, {false,_} = {lists:any(fun(Load) -> Load > 50 end, EmptyScheds1),EmptyScheds1}, {true,_} = {lists:sum(EmptyScheds1) < 60,EmptyScheds1}, %% 50% load HalfHogs = [StartHog() || _ <- lists:seq(1, (Schedulers-1) div 2)], - HalfLoad = lists:sum(get_load()) div Schedulers, + HalfDirtyCPUHogs = [StartDirtyHog(dirty_cpu) + || _ <- lists:seq(1, DirtyCPUSchedulers div 2)], + HalfDirtyIOHogs = [StartDirtyHog(dirty_io) + || _ <- lists:seq(1, DirtyIOSchedulers div 2)], + HalfLoad = lists:sum(get_load(Type)) div TotLoadSchedulers, if Schedulers < 2, HalfLoad > 80 -> ok; %% Ok only one scheduler online and one hog %% We want roughly 50% load HalfLoad > 40, HalfLoad < 60 -> ok; @@ -308,23 +341,30 @@ scheduler_wall_time(Config) when is_list(Config) -> %% 100% load LastHogs = [StartHog() || _ <- lists:seq(1, Schedulers div 2)], - FullScheds = get_load(), + LastDirtyCPUHogs = [StartDirtyHog(dirty_cpu) + || _ <- lists:seq(1, DirtyCPUSchedulers div 2)], + LastDirtyIOHogs = [StartDirtyHog(dirty_io) + || _ <- lists:seq(1, DirtyIOSchedulers div 2)], + FullScheds = get_load(Type), {false,_} = {lists:any(fun(Load) -> Load < 80 end, FullScheds),FullScheds}, - FullLoad = lists:sum(FullScheds) div Schedulers, + FullLoad = lists:sum(FullScheds) div TotLoadSchedulers, if FullLoad > 90 -> ok; true -> exit({fullload, FullLoad}) end, KillHog = fun (HP) -> HPM = erlang:monitor(process, HP), + unlink(HP), exit(HP, kill), receive {'DOWN', HPM, process, HP, killed} -> ok end end, - [KillHog(Pid) || Pid <- [P1|HalfHogs++LastHogs]], - AfterLoad = get_load(), + [KillHog(Pid) || Pid <- [P1|HalfHogs++HalfDirtyCPUHogs++HalfDirtyIOHogs + ++LastHogs++LastDirtyCPUHogs++LastDirtyIOHogs]], + receive after 2000 -> ok end, %% Give dirty schedulers time to complete... + AfterLoad = get_load(Type), io:format("AfterLoad=~p~n", [AfterLoad]), {false,_} = {lists:any(fun(Load) -> Load > 25 end, AfterLoad),AfterLoad}, true = erlang:system_flag(scheduler_wall_time, false) @@ -332,16 +372,81 @@ scheduler_wall_time(Config) when is_list(Config) -> erlang:system_flag(scheduler_wall_time, false) end. -get_load() -> - Start = erlang:statistics(scheduler_wall_time), +get_load(Type) -> + Start = erlang:statistics(Type), timer:sleep(1500), - End = erlang:statistics(scheduler_wall_time), + End = erlang:statistics(Type), lists:reverse(lists:sort(load_percentage(lists:sort(Start),lists:sort(End)))). load_percentage([{Id, WN, TN}|Ss], [{Id, WP, TP}|Ps]) -> [100*(WN-WP) div (TN-TP)|load_percentage(Ss, Ps)]; load_percentage([], []) -> []. +count(0) -> + ok; +count(N) -> + count(N-1). + +msb_swt_hog(true) -> + count(1000000), + erts_debug:dirty_cpu(wait, 10), + erts_debug:dirty_io(wait, 10), + msb_swt_hog(true); +msb_swt_hog(false) -> + count(1000000), + msb_swt_hog(false). + +msb_scheduler_wall_time(Config) -> + erlang:system_flag(scheduler_wall_time, true), + Dirty = erlang:system_info(dirty_cpu_schedulers) /= 0, + Hogs = lists:map(fun (_) -> + spawn_opt(fun () -> + msb_swt_hog(Dirty) + end, [{priority,low}, link, monitor]) + end, lists:seq(1,10)), + erlang:system_flag(multi_scheduling, block), + try + SWT1 = lists:sort(statistics(scheduler_wall_time_all)), + %% io:format("SWT1 = ~p~n", [SWT1]), + receive after 4000 -> ok end, + SWT2 = lists:sort(statistics(scheduler_wall_time_all)), + %% io:format("SWT2 = ~p~n", [SWT2]), + SWT = lists:zip(SWT1, SWT2), + io:format("SU = ~p~n", [lists:map(fun({{I, A0, T0}, {I, A1, T1}}) -> + {I, (A1 - A0)/(T1 - T0)} end, + SWT)]), + {A, T} = lists:foldl(fun({{_, A0, T0}, {_, A1, T1}}, {Ai,Ti}) -> + {Ai + (A1 - A0), Ti + (T1 - T0)} + end, + {0, 0}, + SWT), + TSU = A/T, + WSU = ((TSU * (erlang:system_info(schedulers) + + erlang:system_info(dirty_cpu_schedulers) + + erlang:system_info(dirty_io_schedulers))) + / 1), + %% Weighted scheduler utilization should be + %% very close to 1.0, i.e., we execute the + %% same time as one thread executing all + %% the time... + io:format("WSU = ~p~n", [WSU]), + true = 0.9 < WSU andalso WSU < 1.1, + ok + after + erlang:system_flag(multi_scheduling, unblock), + erlang:system_flag(scheduler_wall_time, false), + lists:foreach(fun ({HP, _HM}) -> + unlink(HP), + exit(HP, kill) + end, Hogs), + lists:foreach(fun ({HP, HM}) -> + receive + {'DOWN', HM, process, HP, _} -> + ok + end + end, Hogs), + ok + end. %% Tests that statistics(garbage_collection) is callable. %% It is not clear how to test anything more. -- cgit v1.2.3 From 52097fab56edbbd8c6f8a57ec3b3f33aa60c5bb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Mon, 1 Aug 2016 14:49:47 +0200 Subject: Update test cases for erlang:hash/2 removal --- erts/emulator/test/binary_SUITE.erl | 2 - erts/emulator/test/fun_SUITE.erl | 35 +-------- erts/emulator/test/hash_SUITE.erl | 44 ++---------- erts/emulator/test/map_SUITE.erl | 24 ------- erts/emulator/test/trace_local_SUITE.erl | 118 +++++++++++++++---------------- 5 files changed, 65 insertions(+), 158 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl index 1c7d278bb0..238a8aa42d 100644 --- a/erts/emulator/test/binary_SUITE.erl +++ b/erts/emulator/test/binary_SUITE.erl @@ -19,7 +19,6 @@ %% -module(binary_SUITE). --compile({nowarn_deprecated_function, {erlang,hash,2}}). %% Tests binaries and the BIFs: %% list_to_binary/1 @@ -392,7 +391,6 @@ test_hash(List) -> Bin = list_to_binary(List), Sbin = make_sub_binary(List), Unaligned = make_unaligned_sub_binary(Sbin), - test_hash_1(Bin, Sbin, Unaligned, fun erlang:hash/2), test_hash_1(Bin, Sbin, Unaligned, fun erlang:phash/2), test_hash_1(Bin, Sbin, Unaligned, fun erlang:phash2/2). diff --git a/erts/emulator/test/fun_SUITE.erl b/erts/emulator/test/fun_SUITE.erl index 26fa955e3c..e4640909aa 100644 --- a/erts/emulator/test/fun_SUITE.erl +++ b/erts/emulator/test/fun_SUITE.erl @@ -19,12 +19,11 @@ %% -module(fun_SUITE). --compile({nowarn_deprecated_function, {erlang,hash,2}}). -export([all/0, suite/0, bad_apply/1,bad_fun_call/1,badarity/1,ext_badarity/1, equality/1,ordering/1, - fun_to_port/1,t_hash/1,t_phash/1,t_phash2/1,md5/1, + fun_to_port/1,t_phash/1,t_phash2/1,md5/1, refc/1,refc_ets/1,refc_dist/1, const_propagation/1,t_arity/1,t_is_function2/1, t_fun_info/1,t_fun_info_mfa/1]). @@ -38,9 +37,9 @@ suite() -> {timetrap, {minutes, 1}}]. -all() -> +all() -> [bad_apply, bad_fun_call, badarity, ext_badarity, - equality, ordering, fun_to_port, t_hash, t_phash, + equality, ordering, fun_to_port, t_phash, t_phash2, md5, refc, refc_ets, refc_dist, const_propagation, t_arity, t_is_function2, t_fun_info, t_fun_info_mfa]. @@ -412,33 +411,6 @@ build_io_list(N) -> 1 -> [7,L|L] end. -%% Test the hash/2 BIF on funs. -t_hash(Config) when is_list(Config) -> - F1 = fun(_X) -> 1 end, - F2 = fun(_X) -> 2 end, - true = hash(F1) /= hash(F2), - - G1 = make_fun(1, 2, 3), - G2 = make_fun(1, 2, 3), - G3 = make_fun(1, 2, 4), - true = hash(G1) == hash(G2), - true = hash(G2) /= hash(G3), - - FF0 = fun erlang:abs/1, - FF1 = fun erlang:exit/1, - FF2 = fun erlang:exit/2, - FF3 = fun blurf:exit/2, - true = hash(FF0) =/= hash(FF1), - true = hash(FF0) =/= hash(FF2), - true = hash(FF0) =/= hash(FF3), - true = hash(FF1) =/= hash(FF2), - true = hash(FF1) =/= hash(FF3), - true = hash(FF2) =/= hash(FF3), - ok. - -hash(Term) -> - erlang:hash(Term, 16#7ffffff). - %% Test the phash/2 BIF on funs. t_phash(Config) when is_list(Config) -> F1 = fun(_X) -> 1 end, @@ -461,7 +433,6 @@ t_phash(Config) when is_list(Config) -> true = phash(FF1) =/= phash(FF2), true = phash(FF1) =/= phash(FF3), true = phash(FF2) =/= phash(FF3), - ok. phash(Term) -> diff --git a/erts/emulator/test/hash_SUITE.erl b/erts/emulator/test/hash_SUITE.erl index a39d101b0d..3cbb3c7d5f 100644 --- a/erts/emulator/test/hash_SUITE.erl +++ b/erts/emulator/test/hash_SUITE.erl @@ -34,7 +34,6 @@ -export([basic_test/0,cmp_test/1,range_test/0,spread_test/1, phash2_test/0, otp_5292_test/0, otp_7127_test/0]). --compile({nowarn_deprecated_function, {erlang,hash,2}}). %% %% Define to run outside of test server @@ -130,24 +129,12 @@ test_hash_zero(Config) when is_list(Config) -> %% basic_test() -> 685556714 = erlang:phash({a,b,c},16#FFFFFFFF), - 14468079 = erlang:hash({a,b,c},16#7FFFFFF), 37442646 = erlang:phash([a,b,c,{1,2,3},c:pid(0,2,3), 16#77777777777777],16#FFFFFFFF), - Comment = case erlang:hash([a,b,c,{1,2,3},c:pid(0,2,3), - 16#77777777777777],16#7FFFFFF) of - 102727602 -> - big = erlang:system_info(endian), - "Big endian machine"; - 105818829 -> - little = erlang:system_info(endian), - "Little endian machine" - end, ExternalReference = <<131,114,0,3,100,0,13,110,111,110,111,100,101,64, 110,111,104,111,115,116,0,0,0,0,122,0,0,0,0,0,0,0,0>>, 1113403635 = erlang:phash(binary_to_term(ExternalReference), 16#FFFFFFFF), - 123 = erlang:hash(binary_to_term(ExternalReference), - 16#7FFFFFF), ExternalFun = <<131,117,0,0,0,3,103,100,0,13,110,111,110,111,100,101,64, 110,111,104,111,115,116,0,0,0,38,0,0,0,0,0,100,0,8,101, 114,108,95,101,118,97,108,97,20,98,5,182,139,98,108,0,0, @@ -166,11 +153,9 @@ basic_test() -> 64,110,111,104,111,115,116,0,0,0,22,0,0,0,0,0,106>>, 170987488 = erlang:phash(binary_to_term(ExternalFun), 16#FFFFFFFF), - 124460689 = erlang:hash(binary_to_term(ExternalFun), - 16#7FFFFFF), case (catch erlang:phash(1,0)) of {'EXIT',{badarg, _}} -> - {comment, Comment}; + ok; _ -> exit(phash_accepted_zero_as_range) end. @@ -193,7 +178,6 @@ range_test() -> end, F(1,16#100000000,F). - spread_test(N) -> test_fun(N,{erlang,phash},16#50000000000,fun(X) -> @@ -419,7 +403,7 @@ phash2_test() -> {"abc"++[1009], 290369864}, {"abc"++[1009]++"de", 4134369195}, {"1234567890123456", 963649519}, - + %% tuple {{}, 221703996}, {{{}}, 2165044361}, @@ -452,30 +436,15 @@ f3(X, Y) -> -endif. otp_5292_test() -> - H = fun(E) -> [erlang:hash(E, 16#7FFFFFF), - erlang:hash(-E, 16#7FFFFFF)] - end, - S1 = md5([md5(hash_int(S, E, H)) || {Start, N, Sz} <- d(), - {S, E} <- int(Start, N, Sz)]), PH = fun(E) -> [erlang:phash(E, 1 bsl 32), erlang:phash(-E, 1 bsl 32), erlang:phash2(E, 1 bsl 32), erlang:phash2(-E, 1 bsl 32)] end, - S2 = md5([md5(hash_int(S, E, PH)) || {Start, N, Sz} <- d(), + S2 = md5([md5(hash_int(S, E, PH)) || {Start, N, Sz} <- d(), {S, E} <- int(Start, N, Sz)]), - Comment = case S1 of - <<4,248,208,156,200,131,7,1,173,13,239,173,112,81,16,174>> -> - big = erlang:system_info(endian), - "Big endian machine"; - <<180,28,33,231,239,184,71,125,76,47,227,241,78,184,176,233>> -> - little = erlang:system_info(endian), - "Little endian machine" - end, <<124,81,198,121,174,233,19,137,10,83,33,80,226,111,238,99>> = S2, - 2 = erlang:hash(1, (1 bsl 27) -1), - {'EXIT', _} = (catch erlang:hash(1, (1 bsl 27))), - {comment, Comment}. + ok. d() -> [%% Start, NumOfIntervals, SizeOfInterval @@ -495,8 +464,6 @@ md5(T) -> erlang:md5(term_to_binary(T)). bit_level_binaries_do() -> - [3511317,7022633,14044578,28087749,56173436,112344123,90467083|_] = - bit_level_all_different(fun erlang:hash/2), [3511317,7022633,14044578,28087749,56173436,112344123,90467083|_] = bit_level_all_different(fun erlang:phash/2), [102233154,19716,102133857,4532024,123369135,24565730,109558721|_] = @@ -535,9 +502,7 @@ bit_level_all_different(Hash) -> Hashes1. test_hash_phash(Bitstr, Rem) -> - Hash = erlang:hash(Bitstr, Rem), Hash = erlang:phash(Bitstr, Rem), - Hash = erlang:hash(unaligned_sub_bitstr(Bitstr), Rem), Hash = erlang:phash(unaligned_sub_bitstr(Bitstr), Rem). test_phash2(Bitstr, Rem) -> @@ -555,7 +520,6 @@ hash_zero_test() -> binary_to_term(<<131,70,128,0,0,0,0,0,0,0>>)], %% -0.0 ok = hash_zero_test(Zs,fun(T) -> erlang:phash2(T, 1 bsl 32) end), ok = hash_zero_test(Zs,fun(T) -> erlang:phash(T, 1 bsl 32) end), - ok = hash_zero_test(Zs,fun(T) -> erlang:hash(T, (1 bsl 27) - 1) end), ok. hash_zero_test([Z|Zs],F) -> diff --git a/erts/emulator/test/map_SUITE.erl b/erts/emulator/test/map_SUITE.erl index 5af676c409..dfa1629112 100644 --- a/erts/emulator/test/map_SUITE.erl +++ b/erts/emulator/test/map_SUITE.erl @@ -18,7 +18,6 @@ %% -module(map_SUITE). -export([all/0, suite/0]). --compile({nowarn_deprecated_function, {erlang,hash,2}}). -export([t_build_and_match_literals/1, t_build_and_match_literals_large/1, t_update_literals/1, t_update_literals_large/1, @@ -2130,8 +2129,6 @@ t_erlang_hash(Config) when is_list(Config) -> ok = t_bif_erlang_phash2(), ok = t_bif_erlang_phash(), - ok = t_bif_erlang_hash(), - ok. t_bif_erlang_phash2() -> @@ -2174,27 +2171,6 @@ t_bif_erlang_phash() -> 2620391445 = erlang:phash(M2,Sz), % 3590546636 ok. -t_bif_erlang_hash() -> - Sz = 1 bsl 27 - 1, - 39684169 = erlang:hash(#{},Sz), % 5158 - 33673142 = erlang:hash(#{ a => 1, "a" => 2, <<"a">> => 3, {a,b} => 4 },Sz), % 71555838 - 95337869 = erlang:hash(#{ 1 => a, 2 => "a", 3 => <<"a">>, 4 => {a,b} },Sz), % 5497225 - 108959561 = erlang:hash(#{ 1 => a },Sz), % 126071654 - 59623150 = erlang:hash(#{ a => 1 },Sz), % 126426236 - - 42775386 = erlang:hash(#{{} => <<>>},Sz), % 101655720 - 71692856 = erlang:hash(#{<<>> => {}},Sz), % 101655720 - - M0 = #{ a => 1, "key" => <<"value">> }, - M1 = maps:remove("key",M0), - M2 = M1#{ "key" => <<"value">> }, - - 70254632 = erlang:hash(M0,Sz), % 38260486 - 59623150 = erlang:hash(M1,Sz), % 126426236 - 70254632 = erlang:hash(M2,Sz), % 38260486 - ok. - - t_map_encode_decode(Config) when is_list(Config) -> <<131,116,0,0,0,0>> = erlang:term_to_binary(#{}), Pairs = [ diff --git a/erts/emulator/test/trace_local_SUITE.erl b/erts/emulator/test/trace_local_SUITE.erl index c297acd78b..5b65889f4a 100644 --- a/erts/emulator/test/trace_local_SUITE.erl +++ b/erts/emulator/test/trace_local_SUITE.erl @@ -19,7 +19,6 @@ %% -module(trace_local_SUITE). --compile({nowarn_deprecated_function, {erlang,hash,2}}). -export([basic_test/0, bit_syntax_test/0, return_test/0, on_and_off_test/0, stack_grow_test/0, @@ -65,7 +64,7 @@ init_per_testcase(_Case, Config) -> Config. -end_per_testcase(_Case, Config) -> +end_per_testcase(_Case, _Config) -> shutdown(), %% Reloading the module will clear all trace patterns, and @@ -78,7 +77,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap, {minutes, 2}}]. -all() -> +all() -> case test_server:is_native(trace_local_SUITE) of true -> [not_run]; false -> @@ -98,7 +97,7 @@ all() -> end. -not_run(Config) when is_list(Config) -> +not_run(Config) when is_list(Config) -> {skipped,"Native code"}. %% Tests basic local call-trace @@ -300,7 +299,7 @@ basic_test() -> NumMatches = erlang:trace_pattern({?MODULE,'_','_'},[],[local]), NumMatches = erlang:trace_pattern({?MODULE,'_','_'},[],[local]), erlang:trace_pattern({?MODULE,slave,'_'},false,[local]), - [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + [1,1,1,997] = apply_slave(?MODULE,exported_wrap,[1]), ?CT(?MODULE,exported_wrap,[1]), ?CT(?MODULE,exported,[1]), ?CT(?MODULE,local,[1]), @@ -308,17 +307,17 @@ basic_test() -> ?CT(?MODULE,local_tail,[1]), erlang:trace_pattern({?MODULE,'_','_'},[],[]), erlang:trace_pattern({?MODULE,slave,'_'},false,[local]), - [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + [1,1,1,997] = apply_slave(?MODULE,exported_wrap,[1]), ?CT(?MODULE,exported_wrap,[1]), - [1,1,1,1] = lambda_slave(fun() -> - exported_wrap(1) - end), - ?NM, + [1,1,1,997] = lambda_slave(fun() -> + exported_wrap(1) + end), + ?NM, erlang:trace_pattern({?MODULE,'_','_'},[],[local]), erlang:trace_pattern({?MODULE,slave,'_'},false,[local]), - [1,1,1,1] = lambda_slave(fun() -> - exported_wrap(1) - end), + [1,1,1,997] = lambda_slave(fun() -> + exported_wrap(1) + end), ?CT(?MODULE,_,_), %% The fun ?CT(?MODULE,exported_wrap,[1]), ?CT(?MODULE,exported,[1]), @@ -379,36 +378,36 @@ return_test() -> setup([call]), erlang:trace_pattern({?MODULE,'_','_'},[{'_',[],[{return_trace}]}], [local]), - erlang:trace_pattern({erlang,hash,'_'},[{'_',[],[{return_trace}]}], + erlang:trace_pattern({erlang,phash2,'_'},[{'_',[],[{return_trace}]}], [local]), erlang:trace_pattern({?MODULE,slave,'_'},false,[local]), - [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), - ?CT(?MODULE,exported_wrap,[1]), + [1,1,1,997] = apply_slave(?MODULE,exported_wrap,[1]), + ?CT(?MODULE,exported_wrap,[1]), ?CT(?MODULE,exported,[1]), ?CT(?MODULE,local,[1]), ?CT(?MODULE,local2,[1]), ?CT(?MODULE,local_tail,[1]), - ?CT(erlang,hash,[1,1]), - ?RF(erlang,hash,2,1), - ?RF(?MODULE,local_tail,1,[1,1]), - ?RF(?MODULE,local2,1,[1,1]), - ?RF(?MODULE,local,1,[1,1,1]), - ?RF(?MODULE,exported,1,[1,1,1,1]), - ?RF(?MODULE,exported_wrap,1,[1,1,1,1]), + ?CT(erlang,phash2,[1,1023]), + ?RF(erlang,phash2,2,997), + ?RF(?MODULE,local_tail,1,[1,997]), + ?RF(?MODULE,local2,1,[1,997]), + ?RF(?MODULE,local,1,[1,1,997]), + ?RF(?MODULE,exported,1,[1,1,1,997]), + ?RF(?MODULE,exported_wrap,1,[1,1,1,997]), shutdown(), setup([call,return_to]), erlang:trace_pattern({?MODULE,'_','_'},[], [local]), - erlang:trace_pattern({erlang,hash,'_'},[], + erlang:trace_pattern({erlang,phash2,'_'},[], [local]), erlang:trace_pattern({?MODULE,slave,'_'},false,[local]), - [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), - ?CT(?MODULE,exported_wrap,[1]), + [1,1,1,997] = apply_slave(?MODULE,exported_wrap,[1]), + ?CT(?MODULE,exported_wrap,[1]), ?CT(?MODULE,exported,[1]), ?CT(?MODULE,local,[1]), ?CT(?MODULE,local2,[1]), ?CT(?MODULE,local_tail,[1]), - ?CT(erlang,hash,[1,1]), + ?CT(erlang,phash2,[1,1023]), ?RT(?MODULE,local_tail,1), ?RT(?MODULE,local,1), ?RT(?MODULE,exported,1), @@ -417,25 +416,25 @@ return_test() -> setup([call,return_to]), erlang:trace_pattern({?MODULE,'_','_'},[{'_',[],[{return_trace}]}], [local]), - erlang:trace_pattern({erlang,hash,'_'},[{'_',[],[{return_trace}]}], + erlang:trace_pattern({erlang,phash2,'_'},[{'_',[],[{return_trace}]}], [local]), erlang:trace_pattern({?MODULE,slave,'_'},false,[local]), - [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), - ?CT(?MODULE,exported_wrap,[1]), + [1,1,1,997] = apply_slave(?MODULE,exported_wrap,[1]), + ?CT(?MODULE,exported_wrap,[1]), ?CT(?MODULE,exported,[1]), ?CT(?MODULE,local,[1]), ?CT(?MODULE,local2,[1]), ?CT(?MODULE,local_tail,[1]), - ?CT(erlang,hash,[1,1]), - ?RF(erlang,hash,2,1), + ?CT(erlang,phash2,[1,1023]), + ?RF(erlang,phash2,2,997), ?RT(?MODULE,local_tail,1), - ?RF(?MODULE,local_tail,1,[1,1]), - ?RF(?MODULE,local2,1,[1,1]), + ?RF(?MODULE,local_tail,1,[1,997]), + ?RF(?MODULE,local2,1,[1,997]), ?RT(?MODULE,local,1), - ?RF(?MODULE,local,1,[1,1,1]), + ?RF(?MODULE,local,1,[1,1,997]), ?RT(?MODULE,exported,1), - ?RF(?MODULE,exported,1,[1,1,1,1]), - ?RF(?MODULE,exported_wrap,1,[1,1,1,1]), + ?RF(?MODULE,exported,1,[1,1,1,997]), + ?RF(?MODULE,exported_wrap,1,[1,1,1,997]), ?RT(?MODULE,slave,2), shutdown(), ?NM, @@ -446,7 +445,6 @@ return_test() -> erlang:trace_pattern({'_','_','_'},[],[local]), apply_slave(erlang,trace,[Pid, false, [all]]), shutdown(), - ok. on_and_off_test() -> @@ -456,72 +454,72 @@ on_and_off_test() -> LocalTail = fun() -> local_tail(1) end, - [1,1] = lambda_slave(LocalTail), + [1,997] = lambda_slave(LocalTail), ?CT(?MODULE,local_tail,[1]), erlang:trace(Pid,true,[return_to]), - [1,1] = lambda_slave(LocalTail), + [1,997] = lambda_slave(LocalTail), ?CT(?MODULE,local_tail,[1]), ?RT(?MODULE,_,_), 0 = erlang:trace_pattern({?MODULE,local_tail,1},[],[global]), - [1,1] = lambda_slave(LocalTail), + [1,997] = lambda_slave(LocalTail), ?NM, 1 = erlang:trace_pattern({?MODULE,exported_wrap,1},[],[global]), - [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + [1,1,1,997] = apply_slave(?MODULE,exported_wrap,[1]), ?CT(?MODULE,exported_wrap,[1]), 1 = erlang:trace_pattern({?MODULE,exported_wrap,1},[],[local]), - [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + [1,1,1,997] = apply_slave(?MODULE,exported_wrap,[1]), ?CT(?MODULE,exported_wrap,[1]), ?RT(?MODULE,slave,2), - 1 = erlang:trace_pattern({erlang,hash,2},[],[local]), - [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + 1 = erlang:trace_pattern({erlang,phash2,2},[],[local]), + [1,1,1,997] = apply_slave(?MODULE,exported_wrap,[1]), ?CT(?MODULE,exported_wrap,[1]), - ?CT(erlang,hash,[1,1]), + ?CT(erlang,phash2,[1,1023]), ?RT(?MODULE,local_tail,1), ?RT(?MODULE,slave,2), erlang:trace(Pid,true,[timestamp]), - [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + [1,1,1,997] = apply_slave(?MODULE,exported_wrap,[1]), ?CTT(?MODULE,exported_wrap,[1]), - ?CTT(erlang,hash,[1,1]), + ?CTT(erlang,phash2,[1,1023]), ?RTT(?MODULE,local_tail,1), ?RTT(?MODULE,slave,2), erlang:trace(Pid,false,[return_to,timestamp]), - [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + [1,1,1,997] = apply_slave(?MODULE,exported_wrap,[1]), ?CT(?MODULE,exported_wrap,[1]), - ?CT(erlang,hash,[1,1]), + ?CT(erlang,phash2,[1,1023]), erlang:trace(Pid,true,[return_to]), - 1 = erlang:trace_pattern({erlang,hash,2},[],[]), - [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + 1 = erlang:trace_pattern({erlang,phash2,2},[],[]), + [1,1,1,997] = apply_slave(?MODULE,exported_wrap,[1]), ?CT(?MODULE,exported_wrap,[1]), - ?CT(erlang,hash,[1,1]), + ?CT(erlang,phash2,[1,1023]), ?RT(?MODULE,slave,2), 1 = erlang:trace_pattern({?MODULE,exported_wrap,1},[],[]), - [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + [1,1,1,997] = apply_slave(?MODULE,exported_wrap,[1]), ?CT(?MODULE,exported_wrap,[1]), - ?CT(erlang,hash,[1,1]), + ?CT(erlang,phash2,[1,1023]), shutdown(), erlang:trace_pattern({'_','_','_'},false,[local]), N = erlang:trace_pattern({erlang,'_','_'},true,[local]), case erlang:trace_pattern({erlang,'_','_'},false,[local]) of - N -> + N -> ok; Else -> exit({number_mismatch, {expected, N}, {got, Else}}) end, case erlang:trace_pattern({erlang,'_','_'},false,[local]) of - N -> + N -> ok; Else2 -> exit({number_mismatch, {expected, N}, {got, Else2}}) end, M = erlang:trace_pattern({erlang,'_','_'},true,[]), case erlang:trace_pattern({erlang,'_','_'},false,[]) of - M -> + M -> ok; Else3 -> exit({number_mismatch, {expected, N}, {got, Else3}}) end, case erlang:trace_pattern({erlang,'_','_'},false,[]) of - M -> + M -> ok; Else4 -> exit({number_mismatch, {expected, N}, {got, Else4}}) @@ -930,7 +928,7 @@ local2(Val) -> local_tail(Val). %% Tail recursive call local_tail(Val) -> - [Val , erlang:hash(1,1)]. + [Val , erlang:phash2(1,1023)]. -- cgit v1.2.3 From 26b59dfe67ef551cd94765557cdd8c79794bcc38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Tue, 31 May 2016 14:28:54 +0200 Subject: Add new AtU8 beam chunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new chunk stores atoms encoded in UTF-8. beam_lib has also been modified to handle the new 'utf8_atoms' attribute while the 'atoms' attribute may be a missing chunk from now on. The binary_to_atom/2 BIF can now encode any utf8 binary with up to 255 characters. The list_to_atom/1 BIF can now accept codepoints higher than 255 with up to 255 characters (thanks to Björn Gustavsson). --- erts/emulator/test/bif_SUITE.erl | 47 ++++++++++++++++++++++++++++++++++----- erts/emulator/test/code_SUITE.erl | 10 ++++----- 2 files changed, 46 insertions(+), 11 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl index f70fb0e501..339c827602 100644 --- a/erts/emulator/test/bif_SUITE.erl +++ b/erts/emulator/test/bif_SUITE.erl @@ -26,7 +26,7 @@ -export([all/0, suite/0, display/1, display_huge/0, erl_bif_types/1,guard_bifs_in_erl_bif_types/1, - shadow_comments/1, + shadow_comments/1,list_to_utf8_atom/1, specs/1,improper_bif_stubs/1,auto_imports/1, t_list_to_existing_atom/1,os_env/1,otp_7526/1, binary_to_atom/1,binary_to_existing_atom/1, @@ -43,7 +43,7 @@ all() -> [erl_bif_types, guard_bifs_in_erl_bif_types, shadow_comments, specs, improper_bif_stubs, auto_imports, t_list_to_existing_atom, os_env, otp_7526, - display, + display, list_to_utf8_atom, atom_to_binary, binary_to_atom, binary_to_existing_atom, erl_crash_dump_bytes, min_max, erlang_halt, is_builtin, error_stacktrace, error_stacktrace_during_call_trace]. @@ -339,6 +339,38 @@ check_stub({_,F,A}, B) -> ct:fail(invalid_body) end. +list_to_utf8_atom(Config) when is_list(Config) -> + 'hello' = atom_roundtrip("hello"), + 'こんにちは' = atom_roundtrip("こんにちは"), + + %% Test all edge cases. + _ = atom_roundtrip([16#80]), + _ = atom_roundtrip([16#7F]), + _ = atom_roundtrip([16#FF]), + _ = atom_roundtrip([16#100]), + _ = atom_roundtrip([16#7FF]), + _ = atom_roundtrip([16#800]), + _ = atom_roundtrip([16#D7FF]), + atom_badarg([16#D800]), + atom_badarg([16#DFFF]), + _ = atom_roundtrip([16#E000]), + _ = atom_roundtrip([16#FFFF]), + _ = atom_roundtrip([16#1000]), + _ = atom_roundtrip([16#10FFFF]), + atom_badarg([16#110000]), + ok. + +atom_roundtrip(String) -> + Atom = list_to_atom(String), + Atom = list_to_existing_atom(String), + String = atom_to_list(Atom), + Atom. + +atom_badarg(String) -> + {'EXIT',{badarg,_}} = (catch list_to_atom(String)), + {'EXIT',{badarg,_}} = (catch list_to_existing_atom(String)), + ok. + t_list_to_existing_atom(Config) when is_list(Config) -> all = list_to_existing_atom("all"), ?MODULE = list_to_existing_atom(?MODULE_STRING), @@ -429,6 +461,8 @@ binary_to_atom(Config) when is_list(Config) -> Long = lists:seq(0, 254), LongAtom = list_to_atom(Long), LongBin = list_to_binary(Long), + UnicodeLongAtom = list_to_atom([$é || _ <- lists:seq(0, 254)]), + UnicodeLongBin = << <<"é"/utf8>> || _ <- lists:seq(0, 254)>>, %% latin1 '' = test_binary_to_atom(<<>>, latin1), @@ -440,12 +474,17 @@ binary_to_atom(Config) when is_list(Config) -> '' = test_binary_to_atom(<<>>, utf8), HalfLongAtom = test_binary_to_atom(HalfLongBin, utf8), HalfLongAtom = test_binary_to_atom(HalfLongBin, unicode), + UnicodeLongAtom = test_binary_to_atom(UnicodeLongBin, utf8), + UnicodeLongAtom = test_binary_to_atom(UnicodeLongBin, unicode), [] = [C || C <- lists:seq(128, 255), begin list_to_atom([C]) =/= test_binary_to_atom(<>, utf8) end], + <<"こんにちは"/utf8>> = + atom_to_binary(test_binary_to_atom(<<"こんにちは"/utf8>>, utf8), utf8), + %% badarg failures. fail_binary_to_atom(atom), fail_binary_to_atom(42), @@ -464,10 +503,6 @@ binary_to_atom(Config) when is_list(Config) -> ?BADARG(binary_to_atom(id(<<255>>), utf8)), ?BADARG(binary_to_atom(id(<<255,0>>), utf8)), ?BADARG(binary_to_atom(id(<<16#C0,16#80>>), utf8)), %Overlong 0. - [?BADARG(binary_to_atom(<>, utf8)) || C <- lists:seq(256, 16#D7FF)], - [?BADARG(binary_to_atom(<>, utf8)) || C <- lists:seq(16#E000, 16#FFFD)], - [?BADARG(binary_to_atom(<>, utf8)) || C <- lists:seq(16#10000, 16#8FFFF)], - [?BADARG(binary_to_atom(<>, utf8)) || C <- lists:seq(16#90000, 16#10FFFF)], %% system_limit failures. ?SYS_LIMIT(binary_to_atom(id(<<0:512/unit:8,255>>), utf8)), diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index b29520ab9f..d07166ed98 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -296,16 +296,16 @@ get_chunk(Config) when is_list(Config) -> {ok,my_code_test,Code} = compile:file(File, [binary]), %% Should work. - Chunk = get_chunk_ok("Atom", Code), - Chunk = get_chunk_ok("Atom", make_sub_binary(Code)), - Chunk = get_chunk_ok("Atom", make_unaligned_sub_binary(Code)), + Chunk = get_chunk_ok("AtU8", Code), + Chunk = get_chunk_ok("AtU8", make_sub_binary(Code)), + Chunk = get_chunk_ok("AtU8", make_unaligned_sub_binary(Code)), %% Should fail. - {'EXIT',{badarg,_}} = (catch code:get_chunk(bit_sized_binary(Code), "Atom")), + {'EXIT',{badarg,_}} = (catch code:get_chunk(bit_sized_binary(Code), "AtU8")), {'EXIT',{badarg,_}} = (catch code:get_chunk(Code, "bad chunk id")), %% Invalid beam code or missing chunk should return 'undefined'. - undefined = code:get_chunk(<<"not a beam module">>, "Atom"), + undefined = code:get_chunk(<<"not a beam module">>, "AtU8"), undefined = code:get_chunk(Code, "XXXX"), ok. -- cgit v1.2.3 From afbec46949f0d31448386234efa89cec78b905e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Mon, 16 Jan 2017 11:52:39 +0100 Subject: erts: Add OS signal tests --- erts/emulator/test/Makefile | 1 + erts/emulator/test/os_signal_SUITE.erl | 354 +++++++++++++++++++++ .../test/os_signal_SUITE_data/Makefile.src | 6 + .../test/os_signal_SUITE_data/os_signal_nif.c | 66 ++++ 4 files changed, 427 insertions(+) create mode 100644 erts/emulator/test/os_signal_SUITE.erl create mode 100644 erts/emulator/test/os_signal_SUITE_data/Makefile.src create mode 100644 erts/emulator/test/os_signal_SUITE_data/os_signal_nif.c (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index 2e48c475d5..5ec6ff1901 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -85,6 +85,7 @@ MODULES= \ num_bif_SUITE \ message_queue_data_SUITE \ op_SUITE \ + os_signal_SUITE \ port_SUITE \ port_bif_SUITE \ process_SUITE \ diff --git a/erts/emulator/test/os_signal_SUITE.erl b/erts/emulator/test/os_signal_SUITE.erl new file mode 100644 index 0000000000..2b9343663d --- /dev/null +++ b/erts/emulator/test/os_signal_SUITE.erl @@ -0,0 +1,354 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2017. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%% +%% File: os_signal_SUITE.erl +%% Author: Björn-Egil Dahlberg +%% Created: 2017-01-13 +%% + +-module(os_signal_SUITE). + +-include_lib("common_test/include/ct.hrl"). +-export([all/0, suite/0]). +-export([init_per_testcase/2, end_per_testcase/2]). +-export([init_per_suite/1, end_per_suite/1]). + +-export([set_alarm/1, fork/0, get_exit_code/1]). + +% Test cases +-export([set_unset/1, + t_sighup/1, + t_sigusr1/1, + t_sigusr2/1, + t_sigterm/1, + t_sigalrm/1, + t_sigchld/1, + t_sigchld_fork/1]). + +-define(signal_server, erl_signal_server). + +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap, {minutes, 2}}]. + +all() -> + case os:type() of + {win32, _} -> []; + _ -> [set_unset, + t_sighup, + t_sigusr1, + t_sigusr2, + t_sigterm, + t_sigalrm, + t_sigchld, + t_sigchld_fork] + end. + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Pid = erlang:whereis(?signal_server), + true = erlang:unregister(?signal_server), + [{signal_server, Pid}|Config]. + +end_per_testcase(_Func, Config) -> + case proplists:get_value(signal_server, Config) of + undefined -> ok; + Pid -> + true = erlang:register(?signal_server, Pid), + ok + end. + +init_per_suite(Config) -> + load_nif(Config), + Config. + +end_per_suite(_Config) -> + ok. + +%% tests + +set_unset(_Config) -> + Signals = [sighup, %sigint, + sigquit, sigill, + sigabrt, + sigalrm, sigterm, + sigusr1, sigusr2, + sigchld, + sigstop, sigtstp], + F1 = fun(Sig) -> true = erts_internal:set_signal(Sig,handle) end, + F2 = fun(Sig) -> true = erts_internal:set_signal(Sig,default) end, + F3 = fun(Sig) -> true = erts_internal:set_signal(Sig,ignore) end, + %% set handle + ok = lists:foreach(F1, Signals), + %% set ignore + ok = lists:foreach(F2, Signals), + %% set default + ok = lists:foreach(F3, Signals), + ok. + +t_sighup(_Config) -> + Pid1 = setup_service(), + OsPid = os:getpid(), + erts_internal:set_signal(sighup, handle), + ok = kill("HUP", OsPid), + ok = kill("HUP", OsPid), + ok = kill("HUP", OsPid), + Msgs1 = fetch_msgs(Pid1), + io:format("Msgs1: ~p~n", [Msgs1]), + [{notify,sighup}, + {notify,sighup}, + {notify,sighup}] = Msgs1, + %% no proc + ok = kill("HUP", OsPid), + ok = kill("HUP", OsPid), + ok = kill("HUP", OsPid), + %% ignore + Pid2 = setup_service(), + erts_internal:set_signal(sighup, ignore), + ok = kill("HUP", OsPid), + ok = kill("HUP", OsPid), + ok = kill("HUP", OsPid), + Msgs2 = fetch_msgs(Pid2), + io:format("Msgs2: ~p~n", [Msgs2]), + [] = Msgs2, + %% reset to handle (it's the default) + erts_internal:set_signal(sighup, handle), + ok. + +t_sigusr1(_Config) -> + Pid1 = setup_service(), + OsPid = os:getpid(), + erts_internal:set_signal(sigusr1, handle), + ok = kill("USR1", OsPid), + ok = kill("USR1", OsPid), + ok = kill("USR1", OsPid), + Msgs1 = fetch_msgs(Pid1), + io:format("Msgs1: ~p~n", [Msgs1]), + [{notify,sigusr1}, + {notify,sigusr1}, + {notify,sigusr1}] = Msgs1, + %% no proc + ok = kill("USR1", OsPid), + ok = kill("USR1", OsPid), + ok = kill("USR1", OsPid), + %% ignore + Pid2 = setup_service(), + erts_internal:set_signal(sigusr1, ignore), + ok = kill("USR1", OsPid), + ok = kill("USR1", OsPid), + ok = kill("USR1", OsPid), + Msgs2 = fetch_msgs(Pid2), + io:format("Msgs2: ~p~n", [Msgs2]), + [] = Msgs2, + %% reset to ignore (it's the default) + erts_internal:set_signal(sigusr1, handle), + ok. + +t_sigusr2(_Config) -> + Pid1 = setup_service(), + OsPid = os:getpid(), + erts_internal:set_signal(sigusr2, handle), + ok = kill("USR2", OsPid), + ok = kill("USR2", OsPid), + ok = kill("USR2", OsPid), + Msgs1 = fetch_msgs(Pid1), + io:format("Msgs1: ~p~n", [Msgs1]), + [{notify,sigusr2}, + {notify,sigusr2}, + {notify,sigusr2}] = Msgs1, + %% no proc + ok = kill("USR2", OsPid), + ok = kill("USR2", OsPid), + ok = kill("USR2", OsPid), + %% ignore + Pid2 = setup_service(), + erts_internal:set_signal(sigusr2, ignore), + ok = kill("USR2", OsPid), + ok = kill("USR2", OsPid), + ok = kill("USR2", OsPid), + Msgs2 = fetch_msgs(Pid2), + io:format("Msgs2: ~p~n", [Msgs2]), + [] = Msgs2, + %% reset to ignore (it's the default) + erts_internal:set_signal(sigusr2, ignore), + ok. + +t_sigterm(_Config) -> + Pid1 = setup_service(), + OsPid = os:getpid(), + erts_internal:set_signal(sigterm, handle), + ok = kill("TERM", OsPid), + ok = kill("TERM", OsPid), + ok = kill("TERM", OsPid), + Msgs1 = fetch_msgs(Pid1), + io:format("Msgs1: ~p~n", [Msgs1]), + [{notify,sigterm}, + {notify,sigterm}, + {notify,sigterm}] = Msgs1, + %% no proc + ok = kill("TERM", OsPid), + ok = kill("TERM", OsPid), + ok = kill("TERM", OsPid), + %% ignore + Pid2 = setup_service(), + erts_internal:set_signal(sigterm, ignore), + ok = kill("TERM", OsPid), + ok = kill("TERM", OsPid), + ok = kill("TERM", OsPid), + Msgs2 = fetch_msgs(Pid2), + io:format("Msgs2: ~p~n", [Msgs2]), + [] = Msgs2, + %% reset to handle (it's the default) + erts_internal:set_signal(sigterm, handle), + ok. + +t_sigchld(_Config) -> + Pid1 = setup_service(), + OsPid = os:getpid(), + erts_internal:set_signal(sigchld, handle), + ok = kill("CHLD", OsPid), + ok = kill("CHLD", OsPid), + ok = kill("CHLD", OsPid), + Msgs1 = fetch_msgs(Pid1), + io:format("Msgs1: ~p~n", [Msgs1]), + [{notify,sigchld}, + {notify,sigchld}, + {notify,sigchld}] = Msgs1, + %% no proc + ok = kill("CHLD", OsPid), + ok = kill("CHLD", OsPid), + ok = kill("CHLD", OsPid), + %% ignore + Pid2 = setup_service(), + erts_internal:set_signal(sigchld, ignore), + ok = kill("CHLD", OsPid), + ok = kill("CHLD", OsPid), + ok = kill("CHLD", OsPid), + Msgs2 = fetch_msgs(Pid2), + io:format("Msgs2: ~p~n", [Msgs2]), + [] = Msgs2, + %% reset to handle (it's the default) + erts_internal:set_signal(sigchld, ignore), + ok. + + +t_sigalrm(_Config) -> + Pid1 = setup_service(), + true = erts_internal:set_signal(sigalrm, handle), + ok = os_signal_SUITE:set_alarm(1), + receive after 3000 -> ok end, + Msgs1 = fetch_msgs(Pid1), + [{notify,sigalrm}] = Msgs1, + io:format("Msgs1: ~p~n", [Msgs1]), + erts_internal:set_signal(sigalrm, ignore), + Pid2 = setup_service(), + ok = os_signal_SUITE:set_alarm(1), + receive after 3000 -> ok end, + Msgs2 = fetch_msgs(Pid2), + [] = Msgs2, + io:format("Msgs2: ~p~n", [Msgs2]), + Pid3 = setup_service(), + erts_internal:set_signal(sigalrm, handle), + ok = os_signal_SUITE:set_alarm(1), + receive after 3000 -> ok end, + Msgs3 = fetch_msgs(Pid3), + [{notify,sigalrm}] = Msgs3, + io:format("Msgs3: ~p~n", [Msgs3]), + erts_internal:set_signal(sigalrm, ignore), + ok. + +t_sigchld_fork(_Config) -> + Pid1 = setup_service(), + true = erts_internal:set_signal(sigchld, handle), + {ok,OsPid} = os_signal_SUITE:fork(), + receive after 3000 -> ok end, + Msgs1 = fetch_msgs(Pid1), + io:format("Msgs1: ~p~n", [Msgs1]), + [{notify,sigchld}] = Msgs1, + {ok,Status} = os_signal_SUITE:get_exit_code(OsPid), + io:format("exit status from ~w : ~w~n", [OsPid,Status]), + 42 = Status, + %% reset to ignore (it's the default) + erts_internal:set_signal(sigchld, ignore), + ok. + + +%% nif stubs + +set_alarm(_Secs) -> no. +fork() -> no. +get_exit_code(_OsPid) -> no. + +%% aux + +setup_service() -> + Pid = spawn_link(fun msgs/0), + true = erlang:register(?signal_server, Pid), + Pid. + +msgs() -> + msgs([]). +msgs(Ms) -> + receive + {Pid, fetch_msgs} -> Pid ! {self(), lists:reverse(Ms)}; + Msg -> + msgs([Msg|Ms]) + end. + +fetch_msgs(Pid) -> + Pid ! {self(), fetch_msgs}, + receive {Pid, Msgs} -> Msgs end. + +kill(Signal, Pid) -> + {0,_} = run("kill", ["-s", Signal, Pid]), + receive after 200 -> ok end, + ok. + +load_nif(Config) -> + Path = proplists:get_value(data_dir, Config), + ok = erlang:load_nif(filename:join(Path,"os_signal_nif"), 0). + +run(Program0, Args) -> run(".", Program0, Args). +run(Cwd, Program0, Args) when is_list(Cwd) -> + Program = case os:find_executable(Program0) of + Path when is_list(Path) -> + Path; + false -> + exit(no) + end, + Options = [{args,Args},binary,exit_status,stderr_to_stdout, + {line,4096}, {cd, Cwd}], + try open_port({spawn_executable,Program}, Options) of + Port -> + run_loop(Port, []) + catch + error:_ -> + exit(no) + end. + +run_loop(Port, Output) -> + receive + {Port,{exit_status,Status}} -> + {Status,lists:reverse(Output)}; + {Port,{data,{eol,Bin}}} -> + run_loop(Port, [Bin|Output]); + _Msg -> + run_loop(Port, Output) + end. diff --git a/erts/emulator/test/os_signal_SUITE_data/Makefile.src b/erts/emulator/test/os_signal_SUITE_data/Makefile.src new file mode 100644 index 0000000000..a7f5cdbba5 --- /dev/null +++ b/erts/emulator/test/os_signal_SUITE_data/Makefile.src @@ -0,0 +1,6 @@ + +NIF_LIBS = os_signal_nif@dll@ + +all: $(NIF_LIBS) + +@SHLIB_RULES@ diff --git a/erts/emulator/test/os_signal_SUITE_data/os_signal_nif.c b/erts/emulator/test/os_signal_SUITE_data/os_signal_nif.c new file mode 100644 index 0000000000..78e1348383 --- /dev/null +++ b/erts/emulator/test/os_signal_SUITE_data/os_signal_nif.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include + +#include + +static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + return 0; +} + +static ERL_NIF_TERM set_alarm(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + int t; + if (!enif_get_int(env, argv[0], &t)) { + return enif_make_badarg(env); + } + + alarm(t); + + return enif_make_atom(env, "ok"); +} + +static ERL_NIF_TERM fork_0(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + pid_t pid; + + pid = fork(); + + if (pid == 0) { + /* child */ + exit(42); + } + + return enif_make_tuple(env, 2, + enif_make_atom(env, "ok"), + enif_make_int(env, (int)pid)); +} + +static ERL_NIF_TERM get_exit_code(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + int x; + pid_t pid; + if (!enif_get_int(env, argv[0], &x)) { + return enif_make_badarg(env); + } + + pid = (pid_t) x; + + waitpid(pid, &x, 0); + + return enif_make_tuple(env, 2, + enif_make_atom(env, "ok"), + enif_make_int(env, WEXITSTATUS(x))); +} + + +static ErlNifFunc nif_funcs[] = +{ + {"set_alarm", 1, set_alarm}, + {"fork", 0, fork_0}, + {"get_exit_code", 1, get_exit_code} +}; + +ERL_NIF_INIT(os_signal_SUITE,nif_funcs,load,NULL,NULL,NULL) -- cgit v1.2.3 From 9ccb988eeb79815a33e0dd138278e0c29ed3ca6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Mon, 23 Jan 2017 16:05:07 +0100 Subject: erts: Do not handle SIGILL * Remove SIGILL from signal whitelist --- erts/emulator/test/os_signal_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/os_signal_SUITE.erl b/erts/emulator/test/os_signal_SUITE.erl index 2b9343663d..7c3950114f 100644 --- a/erts/emulator/test/os_signal_SUITE.erl +++ b/erts/emulator/test/os_signal_SUITE.erl @@ -86,7 +86,7 @@ end_per_suite(_Config) -> set_unset(_Config) -> Signals = [sighup, %sigint, - sigquit, sigill, + sigquit, %sigill, sigabrt, sigalrm, sigterm, sigusr1, sigusr2, -- cgit v1.2.3 From d4bd17da9759af54227891a90d9fb83d5bfe6d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 24 Jan 2017 10:59:30 +0100 Subject: erts: Use os module instead of erts_internal for set_signal/2 * Add specs * Change return signature to 'ok' instead of 'true' --- erts/emulator/test/os_signal_SUITE.erl | 48 +++++++++++++++++----------------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/os_signal_SUITE.erl b/erts/emulator/test/os_signal_SUITE.erl index 7c3950114f..9aa49a453e 100644 --- a/erts/emulator/test/os_signal_SUITE.erl +++ b/erts/emulator/test/os_signal_SUITE.erl @@ -92,9 +92,9 @@ set_unset(_Config) -> sigusr1, sigusr2, sigchld, sigstop, sigtstp], - F1 = fun(Sig) -> true = erts_internal:set_signal(Sig,handle) end, - F2 = fun(Sig) -> true = erts_internal:set_signal(Sig,default) end, - F3 = fun(Sig) -> true = erts_internal:set_signal(Sig,ignore) end, + F1 = fun(Sig) -> ok = os:set_signal(Sig,handle) end, + F2 = fun(Sig) -> ok = os:set_signal(Sig,default) end, + F3 = fun(Sig) -> ok = os:set_signal(Sig,ignore) end, %% set handle ok = lists:foreach(F1, Signals), %% set ignore @@ -106,7 +106,7 @@ set_unset(_Config) -> t_sighup(_Config) -> Pid1 = setup_service(), OsPid = os:getpid(), - erts_internal:set_signal(sighup, handle), + os:set_signal(sighup, handle), ok = kill("HUP", OsPid), ok = kill("HUP", OsPid), ok = kill("HUP", OsPid), @@ -121,7 +121,7 @@ t_sighup(_Config) -> ok = kill("HUP", OsPid), %% ignore Pid2 = setup_service(), - erts_internal:set_signal(sighup, ignore), + os:set_signal(sighup, ignore), ok = kill("HUP", OsPid), ok = kill("HUP", OsPid), ok = kill("HUP", OsPid), @@ -129,13 +129,13 @@ t_sighup(_Config) -> io:format("Msgs2: ~p~n", [Msgs2]), [] = Msgs2, %% reset to handle (it's the default) - erts_internal:set_signal(sighup, handle), + os:set_signal(sighup, handle), ok. t_sigusr1(_Config) -> Pid1 = setup_service(), OsPid = os:getpid(), - erts_internal:set_signal(sigusr1, handle), + os:set_signal(sigusr1, handle), ok = kill("USR1", OsPid), ok = kill("USR1", OsPid), ok = kill("USR1", OsPid), @@ -150,7 +150,7 @@ t_sigusr1(_Config) -> ok = kill("USR1", OsPid), %% ignore Pid2 = setup_service(), - erts_internal:set_signal(sigusr1, ignore), + os:set_signal(sigusr1, ignore), ok = kill("USR1", OsPid), ok = kill("USR1", OsPid), ok = kill("USR1", OsPid), @@ -158,13 +158,13 @@ t_sigusr1(_Config) -> io:format("Msgs2: ~p~n", [Msgs2]), [] = Msgs2, %% reset to ignore (it's the default) - erts_internal:set_signal(sigusr1, handle), + os:set_signal(sigusr1, handle), ok. t_sigusr2(_Config) -> Pid1 = setup_service(), OsPid = os:getpid(), - erts_internal:set_signal(sigusr2, handle), + os:set_signal(sigusr2, handle), ok = kill("USR2", OsPid), ok = kill("USR2", OsPid), ok = kill("USR2", OsPid), @@ -179,7 +179,7 @@ t_sigusr2(_Config) -> ok = kill("USR2", OsPid), %% ignore Pid2 = setup_service(), - erts_internal:set_signal(sigusr2, ignore), + os:set_signal(sigusr2, ignore), ok = kill("USR2", OsPid), ok = kill("USR2", OsPid), ok = kill("USR2", OsPid), @@ -187,13 +187,13 @@ t_sigusr2(_Config) -> io:format("Msgs2: ~p~n", [Msgs2]), [] = Msgs2, %% reset to ignore (it's the default) - erts_internal:set_signal(sigusr2, ignore), + os:set_signal(sigusr2, ignore), ok. t_sigterm(_Config) -> Pid1 = setup_service(), OsPid = os:getpid(), - erts_internal:set_signal(sigterm, handle), + os:set_signal(sigterm, handle), ok = kill("TERM", OsPid), ok = kill("TERM", OsPid), ok = kill("TERM", OsPid), @@ -208,7 +208,7 @@ t_sigterm(_Config) -> ok = kill("TERM", OsPid), %% ignore Pid2 = setup_service(), - erts_internal:set_signal(sigterm, ignore), + os:set_signal(sigterm, ignore), ok = kill("TERM", OsPid), ok = kill("TERM", OsPid), ok = kill("TERM", OsPid), @@ -216,13 +216,13 @@ t_sigterm(_Config) -> io:format("Msgs2: ~p~n", [Msgs2]), [] = Msgs2, %% reset to handle (it's the default) - erts_internal:set_signal(sigterm, handle), + os:set_signal(sigterm, handle), ok. t_sigchld(_Config) -> Pid1 = setup_service(), OsPid = os:getpid(), - erts_internal:set_signal(sigchld, handle), + os:set_signal(sigchld, handle), ok = kill("CHLD", OsPid), ok = kill("CHLD", OsPid), ok = kill("CHLD", OsPid), @@ -237,7 +237,7 @@ t_sigchld(_Config) -> ok = kill("CHLD", OsPid), %% ignore Pid2 = setup_service(), - erts_internal:set_signal(sigchld, ignore), + os:set_signal(sigchld, ignore), ok = kill("CHLD", OsPid), ok = kill("CHLD", OsPid), ok = kill("CHLD", OsPid), @@ -245,19 +245,19 @@ t_sigchld(_Config) -> io:format("Msgs2: ~p~n", [Msgs2]), [] = Msgs2, %% reset to handle (it's the default) - erts_internal:set_signal(sigchld, ignore), + os:set_signal(sigchld, ignore), ok. t_sigalrm(_Config) -> Pid1 = setup_service(), - true = erts_internal:set_signal(sigalrm, handle), + ok = os:set_signal(sigalrm, handle), ok = os_signal_SUITE:set_alarm(1), receive after 3000 -> ok end, Msgs1 = fetch_msgs(Pid1), [{notify,sigalrm}] = Msgs1, io:format("Msgs1: ~p~n", [Msgs1]), - erts_internal:set_signal(sigalrm, ignore), + os:set_signal(sigalrm, ignore), Pid2 = setup_service(), ok = os_signal_SUITE:set_alarm(1), receive after 3000 -> ok end, @@ -265,18 +265,18 @@ t_sigalrm(_Config) -> [] = Msgs2, io:format("Msgs2: ~p~n", [Msgs2]), Pid3 = setup_service(), - erts_internal:set_signal(sigalrm, handle), + os:set_signal(sigalrm, handle), ok = os_signal_SUITE:set_alarm(1), receive after 3000 -> ok end, Msgs3 = fetch_msgs(Pid3), [{notify,sigalrm}] = Msgs3, io:format("Msgs3: ~p~n", [Msgs3]), - erts_internal:set_signal(sigalrm, ignore), + os:set_signal(sigalrm, ignore), ok. t_sigchld_fork(_Config) -> Pid1 = setup_service(), - true = erts_internal:set_signal(sigchld, handle), + ok = os:set_signal(sigchld, handle), {ok,OsPid} = os_signal_SUITE:fork(), receive after 3000 -> ok end, Msgs1 = fetch_msgs(Pid1), @@ -286,7 +286,7 @@ t_sigchld_fork(_Config) -> io:format("exit status from ~w : ~w~n", [OsPid,Status]), 42 = Status, %% reset to ignore (it's the default) - erts_internal:set_signal(sigchld, ignore), + os:set_signal(sigchld, ignore), ok. -- cgit v1.2.3 From b079018e38272604ffacfece9b97924a9e39df5c Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Mon, 23 Jan 2017 17:10:18 +0100 Subject: Implement magic references Magic references are *intentionally* indistinguishable from ordinary references for the Erlang software. Magic references do not change the language, and are intended as a pure runtime internal optimization. An ordinary reference is typically used as a key in some table. A magic reference has a direct pointer to a reference counted magic binary. This makes it possible to implement various things without having to do lookups in a table, but instead access the data directly. Besides very fast lookups this can also improve scalability by removing a potentially contended table. A couple of examples of planned future usage of magic references are ETS table identifiers, and BIF timer identifiers. Besides future optimizations using magic references it should also be possible to replace the exposed magic binary cludge with magic references. That is, magic binaries that are exposed as empty binaries to the Erlang software. --- erts/emulator/test/node_container_SUITE.erl | 41 +++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/node_container_SUITE.erl b/erts/emulator/test/node_container_SUITE.erl index af18545bff..7356f31b75 100644 --- a/erts/emulator/test/node_container_SUITE.erl +++ b/erts/emulator/test/node_container_SUITE.erl @@ -50,7 +50,8 @@ port_wrap/1, bad_nc/1, unique_pid/1, - iter_max_procs/1]). + iter_max_procs/1, + magic_ref/1]). suite() -> [{ct_hooks,[ts_install_cth]}, @@ -62,7 +63,7 @@ all() -> node_table_gc, dist_link_refc, dist_monitor_refc, node_controller_refc, ets_refc, match_spec_refc, timer_refc, otp_4715, pid_wrap, port_wrap, bad_nc, - unique_pid, iter_max_procs]. + unique_pid, iter_max_procs, magic_ref]. init_per_suite(Config) -> Config. @@ -889,10 +890,46 @@ chk_max_proc_line_until(NoMoreTests, Res) -> chk_max_proc_line_until(NoMoreTests, Res) end. +magic_ref(Config) when is_list(Config) -> + {MRef0, Addr0} = erts_debug:set_internal_state(make, magic_ref), + true = is_reference(MRef0), + {Addr0, 1, true} = erts_debug:get_internal_state({magic_ref,MRef0}), + MRef1 = binary_to_term(term_to_binary(MRef0)), + {Addr0, 2, true} = erts_debug:get_internal_state({magic_ref,MRef1}), + MRef0 = MRef1, + Me = self(), + {Pid, Mon} = spawn_opt(fun () -> + receive + {Me, MRef} -> + Me ! {self(), erts_debug:get_internal_state({magic_ref,MRef})} + end + end, + [link, monitor]), + Pid ! {self(), MRef0}, + receive + {Pid, Info} -> + {Addr0, 3, true} = Info + end, + receive + {'DOWN', Mon, process, Pid, _} -> + ok + end, + {Addr0, 2, true} = erts_debug:get_internal_state({magic_ref,MRef0}), + id(MRef0), + id(MRef1), + MRefExt = term_to_binary(erts_debug:set_internal_state(make, magic_ref)), + garbage_collect(), + {MRef2, _Addr2} = binary_to_term(MRefExt), + true = is_reference(MRef2), + true = erts_debug:get_internal_state({magic_ref,MRef2}), + ok. %% %% -- Internal utils --------------------------------------------------------- %% +id(X) -> + X. + -define(ND_REFS, erts_debug:get_internal_state(node_and_dist_references)). node_container_refc_check(Node) when is_atom(Node) -> -- cgit v1.2.3 From 7fee9c57d89be05c980d1684329b26ac991bb26a Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Mon, 23 Jan 2017 17:16:28 +0100 Subject: Use magic refs for NIF resources --- erts/emulator/test/nif_SUITE.erl | 9 +++-- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 56 ++++++++++++++++++--------- 2 files changed, 42 insertions(+), 23 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 36d512e388..8959be8690 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -748,7 +748,7 @@ resource_hugo_do(Type) -> HugoBin = <<"Hugo Hacker">>, HugoPtr = alloc_resource(Type, HugoBin), Hugo = make_resource(HugoPtr), - <<>> = Hugo, + true = is_reference(Hugo), release_resource(HugoPtr), erlang:garbage_collect(), {HugoPtr,HugoBin} = get_resource(Type,Hugo), @@ -782,7 +782,7 @@ resource_otto_do(Type) -> OttoBin = <<"Otto Ordonnans">>, OttoPtr = alloc_resource(Type, OttoBin), Otto = make_resource(OttoPtr), - <<>> = Otto, + true = is_reference(Otto), %% forget resource term but keep referenced by NIF {OttoPtr, OttoBin}. @@ -805,8 +805,9 @@ resource_new_do2(Type) -> BinB = <<"NewB">>, ResA = make_new_resource(Type, BinA), ResB = make_new_resource(Type, BinB), - <<>> = ResA, - <<>> = ResB, + true = is_reference(ResA), + true = is_reference(ResB), + ResA /= ResB, {PtrA,BinA} = get_resource(Type, ResA), {PtrB,BinB} = get_resource(Type, ResB), true = (PtrA =/= PtrB), diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 4decb7f418..7331c5b2cd 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -1027,6 +1027,7 @@ struct make_term_info unsigned reuse_push; unsigned reuse_pull; ErlNifResourceType* resource_type; + void *resource; ERL_NIF_TERM other_term; ERL_NIF_TERM blob; ErlNifPid to_pid; @@ -1139,12 +1140,7 @@ static ERL_NIF_TERM make_term_list0(struct make_term_info* mti, int n) } static ERL_NIF_TERM make_term_resource(struct make_term_info* mti, int n) { - void* resource = enif_alloc_resource(mti->resource_type, 10); - ERL_NIF_TERM term; - fill(resource, 10, n); - term = enif_make_resource(mti->dst_env, resource); - enif_release_resource(resource); - return term; + return enif_make_resource(mti->dst_env, mti->resource); } static ERL_NIF_TERM make_term_new_binary(struct make_term_info* mti, int n) { @@ -1249,23 +1245,39 @@ static int make_term_n(struct make_term_info* mti, int n, ERL_NIF_TERM* res) return 0; } -static ERL_NIF_TERM make_blob(ErlNifEnv* caller_env, ErlNifEnv* dst_env, - ERL_NIF_TERM other_term) + +static void +init_make_blob(struct make_term_info *mti, + ErlNifEnv* caller_env, + ERL_NIF_TERM other_term) { PrivData* priv = (PrivData*) enif_priv_data(caller_env); + mti->caller_env = caller_env; + mti->resource_type = priv->rt_arr[0].t; + mti->resource = enif_alloc_resource(mti->resource_type, 10); + fill(mti->resource, 10, 17); + mti->other_term = other_term; +} + +static void +fini_make_blob(struct make_term_info *mti) +{ + enif_release_resource(mti->resource); +} + +static ERL_NIF_TERM make_blob(struct make_term_info *mti, + ErlNifEnv* dst_env) +{ ERL_NIF_TERM term, list; int n = 0; - struct make_term_info mti; - mti.caller_env = caller_env; - mti.dst_env = dst_env; - mti.dst_env_valid = 1; - mti.reuse_push = 0; - mti.reuse_pull = 0; - mti.resource_type = priv->rt_arr[0].t; - mti.other_term = other_term; + + mti->reuse_push = 0; + mti->reuse_pull = 0; + mti->dst_env = dst_env; + mti->dst_env_valid = 1; list = enif_make_list(dst_env, 0); - while (make_term_n(&mti, n++, &term)) { + while (make_term_n(mti, n++, &term)) { list = enif_make_list_cell(dst_env, term, list); } return list; @@ -1277,13 +1289,16 @@ static ERL_NIF_TERM send_new_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM a ERL_NIF_TERM msg, copy; ErlNifEnv* msg_env; int res; + struct make_term_info mti; if (!enif_get_local_pid(env, argv[0], &to)) { return enif_make_badarg(env); } msg_env = enif_alloc_env(); - msg = make_blob(env,msg_env, argv[1]); - copy = make_blob(env,env, argv[1]); + init_make_blob(&mti, env, argv[1]); + msg = make_blob(&mti,msg_env); + copy = make_blob(&mti,env); + fini_make_blob(&mti); res = enif_send(env, &to, msg_env, msg); enif_free_env(msg_env); return enif_make_tuple3(env, atom_ok, enif_make_int(env,res), copy); @@ -1303,6 +1318,8 @@ static ERL_NIF_TERM alloc_msgenv(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar mti->reuse_push = 0; mti->reuse_pull = 0; mti->resource_type = priv->rt_arr[0].t; + mti->resource = enif_alloc_resource(mti->resource_type, 10); + fill(mti->resource, 10, 17); mti->other_term = enif_make_list(mti->dst_env, 0); mti->blob = enif_make_list(mti->dst_env, 0); mti->mtx = enif_mutex_create("nif_SUITE:mtx"); @@ -1320,6 +1337,7 @@ static void msgenv_dtor(ErlNifEnv* env, void* obj) if (mti->dst_env != NULL) { enif_free_env(mti->dst_env); } + enif_release_resource(mti->resource); enif_mutex_destroy(mti->mtx); enif_cond_destroy(mti->cond); } -- cgit v1.2.3 From 75fdce43ef567668bb89508b9b8ce0df7efaa569 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 6 Feb 2017 17:15:52 +0100 Subject: erts: Add enif_monitor_process and enif_demonitor_process --- erts/emulator/test/nif_SUITE.erl | 248 +++++++++++- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 540 +++++++++++++++++++++++++- erts/emulator/test/nif_SUITE_data/nif_mod.c | 2 + 3 files changed, 780 insertions(+), 10 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 27276e6646..e3af9f7454 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -32,6 +32,12 @@ basic/1, reload_error/1, upgrade/1, heap_frag/1, t_on_load/1, select/1, + monitor_process_a/1, + monitor_process_b/1, + monitor_process_c/1, + monitor_process_d/1, + demonitor_process/1, + monitor_frenzy/1, hipe/1, types/1, many_args/1, binaries/1, get_string/1, get_atom/1, maps/1, @@ -57,6 +63,8 @@ -define(nif_stub,nif_stub_error(?LINE)). +-define(is_resource, is_binary). % to be is_reference + suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> @@ -66,6 +74,8 @@ all() -> ++ [reload_error, heap_frag, types, many_args, select, + {group, monitor}, + monitor_frenzy, hipe, binaries, get_string, get_atom, maps, api_macros, from_array, iolist_as_binary, resource, resource_binary, @@ -83,13 +93,19 @@ all() -> nif_snprintf]. groups() -> - [{G, [], api_repeaters()} || G <- api_groups()]. + [{G, [], api_repeaters()} || G <- api_groups()] + ++ + [{monitor, [], [monitor_process_a, + monitor_process_b, + monitor_process_c, + monitor_process_d, + demonitor_process]}]. + api_groups() -> [api_latest, api_2_4, api_2_0]. api_repeaters() -> [upgrade, resource_takeover, t_on_load]. -init_per_group(api_latest, Config) -> Config; init_per_group(api_2_4, Config) -> [{nif_api_version, ".2_4"} | Config]; init_per_group(api_2_0, Config) -> @@ -99,7 +115,8 @@ init_per_group(api_2_0, Config) -> {skip, "API 2.0 buggy on Windows 64-bit"}; _ -> [{nif_api_version, ".2_0"} | Config] - end. + end; +init_per_group(_, Config) -> Config. end_per_group(_,_) -> ok. @@ -559,6 +576,216 @@ write_full(W, C, Acc) -> Acc end. +%% Basic monitoring of one process that terminates +monitor_process_a(Config) -> + ensure_lib_loaded(Config), + + F = fun(Terminator, UseMsgEnv) -> + Pid = spawn(fun() -> + receive + {exit, Arg} -> exit(Arg); + return -> ok; + BadMatch -> goodmatch = BadMatch + end + end), + R_ptr = alloc_monitor_resource_nif(), + {0, Mon} = monitor_process_nif(R_ptr, Pid, UseMsgEnv, self()), + [R_ptr] = monitored_by(Pid), + Terminator(Pid), + [{monitor_resource_down, R_ptr, Pid, Mon}] = flush(), + [] = last_resource_dtor_call(), + ok = release_resource(R_ptr), + {R_ptr, _, 1} = last_resource_dtor_call() + end, + + T1 = fun(Pid) -> Pid ! {exit, 17} end, + T2 = fun(Pid) -> Pid ! return end, + T3 = fun(Pid) -> Pid ! badmatch end, + T4 = fun(Pid) -> exit(Pid, 18) end, + + [F(T, UME) || T <- [T1,T2,T3,T4], UME <- [true, false]], + + ok. + +%% Test auto-demonitoring at resource destruction +monitor_process_b(Config) -> + ensure_lib_loaded(Config), + + Pid = spawn_link(fun() -> + receive + return -> ok + end + end), + R_ptr = alloc_monitor_resource_nif(), + {0,_} = monitor_process_nif(R_ptr, Pid, true, self()), + [R_ptr] = monitored_by(Pid), + ok = release_resource(R_ptr), + [] = flush(), + {R_ptr, _, 1} = last_resource_dtor_call(), + [] = monitored_by(Pid), + Pid ! return, + ok. + +%% Test termination of monitored process holding last resource ref +monitor_process_c(Config) -> + ensure_lib_loaded(Config), + + Papa = self(), + Pid = spawn_link(fun() -> + R_ptr = alloc_monitor_resource_nif(), + {0,Mon} = monitor_process_nif(R_ptr, self(), true, Papa), + [R_ptr] = monitored_by(self()), + put(store, make_resource(R_ptr)), + ok = release_resource(R_ptr), + [] = last_resource_dtor_call(), + Papa ! {self(), done, R_ptr, Mon}, + exit + end), + [{Pid, done, R_ptr, Mon}, + {monitor_resource_down, R_ptr, Pid, Mon}] = flush(), + {R_ptr, _, 1} = last_resource_dtor_call(), + ok. + +%% Test race of resource dtor called when monitored process is exiting +monitor_process_d(Config) -> + ensure_lib_loaded(Config), + + Papa = self(), + {Target,TRef} = spawn_monitor(fun() -> + nothing = receive_any() + end), + + R_ptr = alloc_monitor_resource_nif(), + {0,_} = monitor_process_nif(R_ptr, Target, true, self()), + [Papa, R_ptr] = monitored_by(Target), + + exit(Target, die), + ok = release_resource(R_ptr), + + [{'DOWN', TRef, process, Target, die}] = flush(), %% no monitor_resource_down + {R_ptr, _, 1} = last_resource_dtor_call(), + + ok. + +%% Test basic demonitoring +demonitor_process(Config) -> + ensure_lib_loaded(Config), + + Pid = spawn_link(fun() -> + receive + return -> ok + end + end), + R_ptr = alloc_monitor_resource_nif(), + {0,MonBin1} = monitor_process_nif(R_ptr, Pid, true, self()), + [R_ptr] = monitored_by(Pid), + {0,MonBin2} = monitor_process_nif(R_ptr, Pid, true, self()), + [R_ptr, R_ptr] = monitored_by(Pid), + 0 = demonitor_process_nif(R_ptr, MonBin1), + [R_ptr] = monitored_by(Pid), + 1 = demonitor_process_nif(R_ptr, MonBin1), + 0 = demonitor_process_nif(R_ptr, MonBin2), + [] = monitored_by(Pid), + 1 = demonitor_process_nif(R_ptr, MonBin2), + + ok = release_resource(R_ptr), + [] = flush(), + {R_ptr, _, 1} = last_resource_dtor_call(), + [] = monitored_by(Pid), + Pid ! return, + ok. + + +monitored_by(Pid) -> + {monitored_by, List0} = process_info(Pid, monitored_by), + List1 = lists:map(fun(E) when ?is_resource(E) -> + {Ptr, _} = get_resource(monitor_resource_type, E), + Ptr; + (E) -> E + end, + List0), + erlang:garbage_collect(), + lists:sort(List1). + +-define(FRENZY_RAND_BITS, 25). + +monitor_frenzy(Config) -> + ensure_lib_loaded(Config), + + Procs1 = processes(), + io:format("~p processes before: ~p\n", [length(Procs1), Procs1]), + + %% Spawn first worker process + Master = self(), + spawn_link(fun() -> + SelfPix = monitor_frenzy_nif(init, ?FRENZY_RAND_BITS, 0, 0), + unlink(Master), + frenzy(SelfPix, undefined) + end), + receive after 5*1000 -> ok end, + + io:format("stats = ~p\n", [monitor_frenzy_nif(stats, 0, 0, 0)]), + + Pids = monitor_frenzy_nif(stop, 0, 0, 0), + io:format("stats = ~p\n", [monitor_frenzy_nif(stats, 0, 0, 0)]), + + lists:foreach(fun(P) -> exit(P, stop) end, Pids), + + io:format("stats = ~p\n", [monitor_frenzy_nif(stats, 0, 0, 0)]), + + Procs2 = processes(), + io:format("~p processes after: ~p\n", [length(Procs2), Procs2]), + ok. + + +frenzy(_SelfPix, done) -> + ok; +frenzy(SelfPix, State0) -> + Rnd = rand:uniform(1 bsl (?FRENZY_RAND_BITS+2)) - 1, + Op = Rnd band 3, + State1 = frenzy_do_op(SelfPix, Op, (Rnd bsr 2), State0), + frenzy(SelfPix, State1). + +frenzy_do_op(SelfPix, Op, Rnd, Pid0) -> + case Op of + 0 -> % add/remove process + Papa = self(), + NewPid = case Pid0 of + undefined -> % Prepare new process to be added + spawn(fun() -> + MRef = monitor(process, Papa), + case receive_any() of + {go, MyPix, MyState} -> + demonitor(MRef, [flush]), + frenzy(MyPix, MyState); + {'DOWN', MRef, process, Papa, _} -> + ok + end + end); + _ -> + Pid0 + end, + case monitor_frenzy_nif(Op, Rnd, SelfPix, NewPid) of + NewPix when is_integer(NewPix) -> + NewPid ! {go, NewPix, undefined}, + undefined; + ExitPid when is_pid(ExitPid) -> + false = (ExitPid =:= self()), + exit(ExitPid,die), + NewPid; + done -> + done + end; + _ -> + case monitor_frenzy_nif(Op, Rnd, SelfPix, undefined) of + ok -> Pid0; + 0 -> Pid0; + 1 -> Pid0; + done -> done + end + end. + + hipe(Config) when is_list(Config) -> Data = proplists:get_value(data_dir, Config), Priv = proplists:get_value(priv_dir, Config), @@ -814,6 +1041,7 @@ maps(Config) when is_list(Config) -> {1, M2} = make_map_remove_nif(M2, "key3"), {0, undefined} = make_map_remove_nif(self(), key), + verify_tmpmem(TmpMem), ok. %% Test macros enif_make_list and enif_make_tuple @@ -1302,7 +1530,7 @@ resource_takeover(Config) when is_list(Config) -> [{load,1,1,101},{get_priv_data_ptr,1,2,102}] = nif_mod_call_history(), {NA7,BinNA7} = make_resource(0, Holder, "NA7"), - {AN7,BinAN7} = make_resource(1, Holder, "AN7"), + {AN7,_BinAN7} = make_resource(1, Holder, "AN7"), ok = forget_resource(NA7), [{{resource_dtor_A_v1,BinNA7},1,_,_}] = nif_mod_call_history(), @@ -1793,7 +2021,7 @@ otp_9828(Config) -> ensure_lib_loaded(Config, 1), otp_9828_loop(<<"I'm alive!">>, 1000). -otp_9828_loop(Bin, 0) -> +otp_9828_loop(_Bin, 0) -> ok; otp_9828_loop(Bin, Val) -> WrtBin = <>, @@ -2075,7 +2303,7 @@ nif_raise_exceptions(NifFunc) -> -define(ERL_NIF_TIME_ERROR, -9223372036854775808). -define(TIME_UNITS, [second, millisecond, microsecond, nanosecond]). -nif_monotonic_time(Config) -> +nif_monotonic_time(_Config) -> ?ERL_NIF_TIME_ERROR = monotonic_time(invalid_time_unit), mtime_loop(1000000). @@ -2100,7 +2328,7 @@ chk_mtime([TU|TUs]) -> end, chk_mtime(TUs). -nif_time_offset(Config) -> +nif_time_offset(_Config) -> ?ERL_NIF_TIME_ERROR = time_offset(invalid_time_unit), toffs_loop(1000000). @@ -2138,7 +2366,7 @@ chk_toffs([TU|TUs]) -> end, chk_toffs(TUs). -nif_convert_time_unit(Config) -> +nif_convert_time_unit(_Config) -> ?ERL_NIF_TIME_ERROR = convert_time_unit(0, second, invalid_time_unit), ?ERL_NIF_TIME_ERROR = convert_time_unit(0, invalid_time_unit, second), ?ERL_NIF_TIME_ERROR = convert_time_unit(0, invalid_time_unit, invalid_time_unit), @@ -2413,6 +2641,10 @@ write_nif(_,_) -> ?nif_stub. read_nif(_,_) -> ?nif_stub. is_closed_nif(_) -> ?nif_stub. last_fd_stop_call() -> ?nif_stub. +alloc_monitor_resource_nif() -> ?nif_stub. +monitor_process_nif(_,_,_,_) -> ?nif_stub. +demonitor_process_nif(_,_) -> ?nif_stub. +monitor_frenzy_nif(_,_,_,_) -> ?nif_stub. %% maps is_map_nif(_) -> ?nif_stub. diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index c4f9611ec8..ee925512d2 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -31,6 +31,27 @@ #include "nif_mod.h" +#if 0 +static ErlNifMutex* dbg_trace_lock; +#define DBG_TRACE_INIT dbg_trace_lock = enif_mutex_create("nif_SUITE.DBG_TRACE") +#define DBG_TRACE_FINI enif_mutex_destroy(dbg_trace_lock) +#define DBG_TRACE_LOCK enif_mutex_lock(dbg_trace_lock) +#define DBG_TRACE_UNLOCK enif_mutex_unlock(dbg_trace_lock) +#define DBG_TRACE0(FMT) do {DBG_TRACE_LOCK; enif_fprintf(stderr, FMT); DBG_TRACE_UNLOCK; }while(0) +#define DBG_TRACE1(FMT, A) do {DBG_TRACE_LOCK; enif_fprintf(stderr, FMT, A); DBG_TRACE_UNLOCK; }while(0) +#define DBG_TRACE2(FMT, A, B) do {DBG_TRACE_LOCK; enif_fprintf(stderr, FMT, A, B); DBG_TRACE_UNLOCK; }while(0) +#define DBG_TRACE3(FMT, A, B, C) do {DBG_TRACE_LOCK; enif_fprintf(stderr, FMT, A, B, C); DBG_TRACE_UNLOCK; }while(0) +#define DBG_TRACE4(FMT, A, B, C, D) do {DBG_TRACE_LOCK; enif_fprintf(stderr, FMT, A, B, C, D); DBG_TRACE_UNLOCK; }while(0) +#else +#define DBG_TRACE_INIT +#define DBG_TRACE_FINI +#define DBG_TRACE0(FMT) +#define DBG_TRACE1(FMT, A) +#define DBG_TRACE2(FMT, A, B) +#define DBG_TRACE3(FMT, A, B, C) +#define DBG_TRACE4(FMT, A, B, C, D) +#endif + static int static_cntA; /* zero by default */ static int static_cntB = NIF_SUITE_LIB_VER * 100; @@ -48,6 +69,12 @@ static ERL_NIF_TERM atom_eagain; static ERL_NIF_TERM atom_eof; static ERL_NIF_TERM atom_error; static ERL_NIF_TERM atom_fd_resource_stop; +static ERL_NIF_TERM atom_monitor_resource_type; +static ERL_NIF_TERM atom_monitor_resource_down; +static ERL_NIF_TERM atom_init; +static ERL_NIF_TERM atom_stats; +static ERL_NIF_TERM atom_done; +static ERL_NIF_TERM atom_stop; typedef struct { @@ -120,6 +147,27 @@ struct fd_resource { ErlNifPid pid; }; +static ErlNifResourceType* monitor_resource_type; +static void monitor_resource_dtor(ErlNifEnv* env, void* obj); +static void monitor_resource_down(ErlNifEnv*, void* obj, ErlNifPid*, ErlNifMonitor*); +static ErlNifResourceTypeInit monitor_rt_init = { + monitor_resource_dtor, + NULL, + monitor_resource_down +}; +struct monitor_resource { + ErlNifPid receiver; + int use_msgenv; +}; + +static ErlNifResourceType* frenzy_resource_type; +static void frenzy_resource_dtor(ErlNifEnv* env, void* obj); +static void frenzy_resource_down(ErlNifEnv*, void* obj, ErlNifPid*, ErlNifMonitor*); +static ErlNifResourceTypeInit frenzy_rt_init = { + frenzy_resource_dtor, + NULL, + frenzy_resource_down +}; static int get_pointer(ErlNifEnv* env, ERL_NIF_TERM term, void** pp) { @@ -148,6 +196,8 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) data->call_history = NULL; data->nif_mod = NULL; + DBG_TRACE_INIT; + add_call(env, data, "load"); data->rt_arr[0].t = enif_open_resource_type(env,NULL,"Gold",resource_dtor, @@ -165,6 +215,13 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) fd_resource_type = enif_open_resource_type_x(env, "nif_SUITE.fd", &fd_rt_init, ERL_NIF_RT_CREATE, NULL); + monitor_resource_type = enif_open_resource_type_x(env, "nif_SUITE.monitor", + &monitor_rt_init, + ERL_NIF_RT_CREATE, NULL); + frenzy_resource_type = enif_open_resource_type_x(env, "nif_SUITE.monitor_frenzy", + &frenzy_rt_init, + ERL_NIF_RT_CREATE, NULL); + atom_false = enif_make_atom(env,"false"); atom_true = enif_make_atom(env,"true"); atom_self = enif_make_atom(env,"self"); @@ -179,6 +236,12 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_eof = enif_make_atom(env, "eof"); atom_error = enif_make_atom(env, "error"); atom_fd_resource_stop = enif_make_atom(env, "fd_resource_stop"); + atom_monitor_resource_type = enif_make_atom(env, "monitor_resource_type"); + atom_monitor_resource_down = enif_make_atom(env, "monitor_resource_down"); + atom_init = enif_make_atom(env,"init"); + atom_stats = enif_make_atom(env,"stats"); + atom_done = enif_make_atom(env,"done"); + atom_stop = enif_make_atom(env,"stop"); *priv_data = data; return 0; @@ -232,6 +295,7 @@ static void unload(ErlNifEnv* env, void* priv_data) } enif_free(priv_data); } + DBG_TRACE_FINI; } static ERL_NIF_TERM lib_version(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) @@ -855,6 +919,9 @@ static ERL_NIF_TERM get_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar if (enif_is_identical(argv[0], atom_binary_resource_type)) { type.t = binary_resource_type; } + else if (enif_is_identical(argv[0], atom_monitor_resource_type)) { + type.t = monitor_resource_type; + } else { get_pointer(env, argv[0], &type.vp); } @@ -1496,7 +1563,6 @@ static ERL_NIF_TERM send_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ static ERL_NIF_TERM send_copy_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - ErlNifEnv* menv; ErlNifPid pid; int ret; if (!enif_get_local_pid(env, argv[0], &pid)) { @@ -2236,6 +2302,472 @@ static ERL_NIF_TERM last_fd_stop_call(ErlNifEnv* env, int argc, const ERL_NIF_TE } +static void monitor_resource_dtor(ErlNifEnv* env, void* obj) +{ + resource_dtor(env, obj); +} + +static ERL_NIF_TERM make_monitor(ErlNifEnv* env, const ErlNifMonitor* mon) +{ + ERL_NIF_TERM mon_bin; + memcpy(enif_make_new_binary(env, sizeof(ErlNifMonitor), &mon_bin), + mon, sizeof(ErlNifMonitor)); + return mon_bin; +} + +static int get_monitor(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifMonitor* mon) +{ + ErlNifBinary bin; + if (!enif_inspect_binary(env, term, &bin) + || bin.size != sizeof(ErlNifMonitor)) + return 0; + memcpy(mon, bin.data, bin.size); + return 1; +} + +static void monitor_resource_down(ErlNifEnv* env, void* obj, ErlNifPid* pid, + ErlNifMonitor* mon) +{ + struct monitor_resource* rsrc = (struct monitor_resource*)obj; + ErlNifEnv* build_env; + ErlNifEnv* msg_env; + ERL_NIF_TERM msg; + + if (rsrc->use_msgenv) { + msg_env = enif_alloc_env(); + build_env = msg_env; + } + else { + msg_env = NULL; + build_env = env; + } + + msg = enif_make_tuple4(build_env, + atom_monitor_resource_down, + make_pointer(build_env, obj), + enif_make_pid(build_env, pid), + make_monitor(build_env, mon)); + + enif_send(env, &rsrc->receiver, msg_env, msg); + if (msg_env) + enif_free_env(msg_env); +} + +static ERL_NIF_TERM alloc_monitor_resource_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + struct monitor_resource* rsrc; + + rsrc = enif_alloc_resource(monitor_resource_type, sizeof(struct monitor_resource)); + + return make_pointer(env,rsrc); +} + +static ERL_NIF_TERM monitor_process_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + struct monitor_resource* rsrc; + ErlNifPid target; + ErlNifMonitor mon; + int res; + + if (!get_pointer(env, argv[0], (void**)&rsrc) + || !enif_get_local_pid(env, argv[1], &target) + || !enif_get_local_pid(env, argv[3], &rsrc->receiver)) { + return enif_make_badarg(env); + } + + rsrc->use_msgenv = (argv[2] == atom_true); + res = enif_monitor_process(env, rsrc, &target, &mon); + + return enif_make_tuple2(env, enif_make_int(env, res), make_monitor(env, &mon)); +} + +static ERL_NIF_TERM demonitor_process_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + struct monitor_resource* rsrc; + ErlNifMonitor mon; + int res; + + if (!get_pointer(env, argv[0], (void**)&rsrc) + || !get_monitor(env, argv[1], &mon)) { + return enif_make_badarg(env); + } + + res = enif_demonitor_process(env, rsrc, &mon); + + return enif_make_int(env, res); +} + +/*********** monitor_frenzy ************/ + +struct frenzy_rand_bits +{ + unsigned int source; + unsigned int bits_consumed; +}; + +static unsigned int frenzy_rand_bits_max; + +unsigned rand_bits(struct frenzy_rand_bits* rnd, unsigned int nbits) +{ + unsigned int res; + + rnd->bits_consumed += nbits; + assert(rnd->bits_consumed <= frenzy_rand_bits_max); + res = rnd->source & ((1 << nbits)-1); + rnd->source >>= nbits; + return res; +} + +#define FRENZY_PROCS_MAX_BITS 4 +#define FRENZY_PROCS_MAX (1 << FRENZY_PROCS_MAX_BITS) + +#define FRENZY_RESOURCES_MAX_BITS 4 +#define FRENZY_RESOURCES_MAX (1 << FRENZY_RESOURCES_MAX_BITS) + +#define FRENZY_MONITORS_MAX_BITS 4 +#define FRENZY_MONITORS_MAX (1 << FRENZY_MONITORS_MAX_BITS) + +struct frenzy_monitor { + ErlNifMutex* lock; + enum { + MON_FREE, MON_FREE_DOWN, MON_FREE_DEMONITOR, + MON_TRYING, MON_ACTIVE, MON_PENDING + } state; + ErlNifMonitor mon; + ErlNifPid pid; + unsigned int use_cnt; +}; + +struct frenzy_resource { + unsigned int rix; + struct frenzy_monitor monv[FRENZY_MONITORS_MAX]; +}; +struct frenzy_reslot { + ErlNifMutex* lock; + struct frenzy_resource* obj; + unsigned long alloc_cnt; + unsigned long release_cnt; +}; +static struct frenzy_reslot resv[FRENZY_RESOURCES_MAX]; + +static ERL_NIF_TERM monitor_frenzy_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + struct frenzy_proc { + ErlNifPid pid; + int is_free; + }; + static struct frenzy_proc procs[FRENZY_PROCS_MAX]; + static struct frenzy_proc* proc_refs[FRENZY_PROCS_MAX]; + static unsigned int nprocs, old_nprocs; + static ErlNifMutex* procs_lock; + static unsigned long spawn_cnt = 0; + static unsigned long kill_cnt = 0; + static unsigned long proc_histogram[FRENZY_PROCS_MAX]; + + static const unsigned int primes[] = {7, 13, 17, 19}; + + struct frenzy_resource* r; + struct frenzy_rand_bits rnd; + unsigned int op, inc, my_nprocs; + unsigned int mix; /* r->monv[] index */ + unsigned int rix; /* resv[] index */ + unsigned int pix; /* procs[] index */ + unsigned int ref_ix; /* proc_refs[] index */ + int self_pix, rv; + ERL_NIF_TERM retval = atom_error; + const ERL_NIF_TERM Op = argv[0]; + const ERL_NIF_TERM Rnd = argv[1]; + const ERL_NIF_TERM SelfPix = argv[2]; + const ERL_NIF_TERM NewPid = argv[3]; + + if (enif_is_atom(env, Op)) { + if (Op == atom_init) { + if (procs_lock || !enif_get_uint(env, Rnd, &frenzy_rand_bits_max)) + return enif_make_badarg(env); + + procs_lock = enif_mutex_create("nif_SUITE:monitor_frenzy.procs"); + nprocs = 0; + old_nprocs = 0; + for (pix = 0; pix < FRENZY_PROCS_MAX; pix++) { + proc_refs[pix] = &procs[pix]; + procs[pix].is_free = 1; + proc_histogram[pix] = 0; + } + for (rix = 0; rix < FRENZY_RESOURCES_MAX; rix++) { + resv[rix].lock = enif_mutex_create("nif_SUITE:monitor_frenzy.resv.lock"); + resv[rix].obj = NULL; + resv[rix].alloc_cnt = 0; + resv[rix].release_cnt = 0; + } + + /* Add self as first process */ + enif_self(env, &procs[0].pid); + procs[0].is_free = 0; + old_nprocs = ++nprocs; + + spawn_cnt = 1; + kill_cnt = 0; + return enif_make_uint(env, 0); /* SelfPix */ + } + else if (Op == atom_stats) { + ERL_NIF_TERM hist[FRENZY_PROCS_MAX]; + unsigned long res_alloc_cnt = 0; + unsigned long res_release_cnt = 0; + for (ref_ix = 0; ref_ix < FRENZY_PROCS_MAX; ref_ix++) { + hist[ref_ix] = enif_make_ulong(env, proc_histogram[ref_ix]); + } + for (rix = 0; rix < FRENZY_RESOURCES_MAX; rix++) { + res_alloc_cnt += resv[rix].alloc_cnt; + res_release_cnt += resv[rix].release_cnt; + } + + return + enif_make_list4(env, + enif_make_tuple2(env, enif_make_string(env, "proc_histogram", ERL_NIF_LATIN1), + enif_make_list_from_array(env, hist, FRENZY_PROCS_MAX)), + enif_make_tuple2(env, enif_make_string(env, "spawn_cnt", ERL_NIF_LATIN1), + enif_make_ulong(env, spawn_cnt)), + enif_make_tuple2(env, enif_make_string(env, "kill_cnt", ERL_NIF_LATIN1), + enif_make_ulong(env, kill_cnt)), + enif_make_tuple3(env, enif_make_string(env, "resource_alloc", ERL_NIF_LATIN1), + enif_make_ulong(env, res_alloc_cnt), + enif_make_ulong(env, res_release_cnt))); + + } + else if (Op == atom_stop && procs_lock) { /* stop all */ + retval = enif_make_list(env, 0); + enif_mutex_lock(procs_lock); + for (ref_ix = 0; ref_ix < nprocs; ref_ix++) { + assert(!proc_refs[ref_ix]->is_free); + retval = enif_make_list_cell(env, enif_make_pid(env, &proc_refs[ref_ix]->pid), + retval); + proc_refs[ref_ix]->is_free = 1; + } + kill_cnt += nprocs; + nprocs = 0; + old_nprocs = 0; + enif_mutex_unlock(procs_lock); + return retval; + } + return enif_make_badarg(env); + } + + if (!enif_get_int(env, SelfPix, &self_pix) || + !enif_get_uint(env, Op, &op) || + !enif_get_uint(env, Rnd, &rnd.source)) + return enif_make_badarg(env); + + rnd.bits_consumed = 0; + switch (op) { + case 0: { /* add/remove process */ + ErlNifPid self; + enif_self(env, &self); + + ref_ix = rand_bits(&rnd, FRENZY_PROCS_MAX_BITS) % FRENZY_PROCS_MAX; + enif_mutex_lock(procs_lock); + if (procs[self_pix].is_free || procs[self_pix].pid.pid != self.pid) { + /* Some one already removed me */ + enif_mutex_unlock(procs_lock); + return atom_done; + } + if (ref_ix >= nprocs || nprocs < 2) { /* add process */ + ref_ix = nprocs++; + pix = proc_refs[ref_ix] - procs; + assert(procs[pix].is_free); + if (!enif_get_local_pid(env, NewPid, &procs[pix].pid)) + abort(); + procs[pix].is_free = 0; + spawn_cnt++; + proc_histogram[ref_ix]++; + old_nprocs = nprocs; + enif_mutex_unlock(procs_lock); + DBG_TRACE2("Add pid %T, nprocs = %u\n", NewPid, nprocs); + retval = enif_make_uint(env, pix); + } + else { /* remove process */ + pix = proc_refs[ref_ix] - procs; + if (pix == self_pix) { + ref_ix = (ref_ix + 1) % nprocs; + pix = proc_refs[ref_ix] - procs; + } + assert(procs[pix].pid.pid != self.pid); + assert(!procs[pix].is_free); + retval = enif_make_pid(env, &procs[pix].pid); + --nprocs; + assert(!proc_refs[nprocs]->is_free); + if (ref_ix != nprocs) { + struct frenzy_proc* tmp = proc_refs[ref_ix]; + proc_refs[ref_ix] = proc_refs[nprocs]; + proc_refs[nprocs] = tmp; + } + procs[pix].is_free = 1; + proc_histogram[nprocs]++; + kill_cnt++; + enif_mutex_unlock(procs_lock); + DBG_TRACE2("Removed pid %T, nprocs = %u\n", retval, nprocs); + } + break; + } + case 1: + case 2: /* create/delete/lookup resource */ + rix = rand_bits(&rnd, FRENZY_RESOURCES_MAX_BITS) % FRENZY_RESOURCES_MAX; + inc = primes[rand_bits(&rnd, 2)]; + while (enif_mutex_trylock(resv[rix].lock) == EBUSY) { + rix = (rix + inc) % FRENZY_RESOURCES_MAX; + } + if (resv[rix].obj == NULL) { + r = enif_alloc_resource(frenzy_resource_type, + sizeof(struct frenzy_resource)); + resv[rix].obj = r; + resv[rix].alloc_cnt++; + r->rix = rix; + for (mix = 0; mix < FRENZY_MONITORS_MAX; mix++) { + r->monv[mix].lock = enif_mutex_create("nif_SUITE:monitor_frenzy.monv.lock"); + r->monv[mix].state = MON_FREE; + r->monv[mix].use_cnt = 0; + r->monv[mix].pid.pid = 0; /* null-pid */ + } + DBG_TRACE2("New resource at r=%p rix=%u\n", r, rix); + } + else if (rand_bits(&rnd, 3) == 0) { + r = resv[rix].obj; + resv[rix].obj = NULL; + resv[rix].release_cnt++; + enif_mutex_unlock(resv[rix].lock); + DBG_TRACE2("Delete resource at r=%p rix=%u\n", r, rix); + enif_release_resource(r); + retval = atom_ok; + break; + } + else { + r = resv[rix].obj; + } + enif_keep_resource(r); + enif_mutex_unlock(resv[rix].lock); + + /* monitor/demonitor */ + + mix = rand_bits(&rnd, FRENZY_MONITORS_MAX_BITS) % FRENZY_MONITORS_MAX; + inc = primes[rand_bits(&rnd, 2)]; + while (enif_mutex_trylock(r->monv[mix].lock) == EBUSY) { + mix = (mix + inc) % FRENZY_MONITORS_MAX; + } + switch (r->monv[mix].state) { + case MON_FREE: + case MON_FREE_DOWN: + case MON_FREE_DEMONITOR: { /* do monitor */ + /* + * Use an old possibly larger value of 'nprocs', to increase + * probability of monitoring an already terminated process + */ + my_nprocs = old_nprocs; + if (my_nprocs > 0) { + int save_state = r->monv[mix].state; + ref_ix = rand_bits(&rnd, FRENZY_PROCS_MAX_BITS) % my_nprocs; + pix = proc_refs[ref_ix] - procs; + r->monv[mix].pid.pid = procs[pix].pid.pid; /* "atomic" */ + r->monv[mix].state = MON_TRYING; + rv = enif_monitor_process(env, r, &r->monv[mix].pid, &r->monv[mix].mon); + if (rv == 0) { + r->monv[mix].state = MON_ACTIVE; + r->monv[mix].use_cnt++; + DBG_TRACE3("Monitor from r=%p rix=%u to %T\n", + r, r->rix, r->monv[mix].pid.pid); + } + else { + r->monv[mix].state = save_state; + DBG_TRACE4("Monitor from r=%p rix=%u to %T FAILED with %d\n", + r, r->rix, r->monv[mix].pid.pid, rv); + } + retval = enif_make_int(env,rv); + } + else { + DBG_TRACE0("No pids to monitor\n"); + retval = atom_ok; + } + break; + } + case MON_ACTIVE: /* do demonitor */ + rv = enif_demonitor_process(env, r, &r->monv[mix].mon); + if (rv == 0) { + DBG_TRACE3("Demonitor from r=%p rix=%u to %T\n", + r, r->rix, r->monv[mix].pid.pid); + r->monv[mix].state = MON_FREE_DEMONITOR; + } + else { + DBG_TRACE4("Demonitor from r=%p rix=%u to %T FAILED with %d\n", + r, r->rix, r->monv[mix].pid.pid, rv); + r->monv[mix].state = MON_PENDING; + } + retval = enif_make_int(env,rv); + break; + + case MON_PENDING: /* waiting for 'down' callback, do nothing */ + retval = atom_ok; + break; + default: + abort(); + break; + } + enif_mutex_unlock(r->monv[mix].lock); + enif_release_resource(r); + break; + + case 3: /* no-op */ + retval = atom_ok; + break; + } + + { + int percent = (rand_bits(&rnd, 6) + 1) * 2; /* 2 to 128 */ + if (percent <= 100) + enif_consume_timeslice(env, percent); + } + + return retval; +} + +static void frenzy_resource_dtor(ErlNifEnv* env, void* obj) +{ + struct frenzy_resource* r = (struct frenzy_resource*) obj; + unsigned int mix; + + DBG_TRACE2("DTOR r=%p rix=%u\n", r, r->rix); + + for (mix = 0; mix < FRENZY_MONITORS_MAX; mix++) { + assert(r->monv[mix].state != MON_PENDING); + enif_mutex_destroy(r->monv[mix].lock); + r->monv[mix].lock = NULL; + } + +} + +static void frenzy_resource_down(ErlNifEnv* env, void* obj, ErlNifPid* pid, + ErlNifMonitor* mon) +{ + struct frenzy_resource* r = (struct frenzy_resource*) obj; + unsigned int mix; + + DBG_TRACE3("DOWN pid=%T, r=%p rix=%u\n", pid->pid, r, r->rix); + + for (mix = 0; mix < FRENZY_MONITORS_MAX; mix++) { + if (r->monv[mix].pid.pid == pid->pid && r->monv[mix].state >= MON_TRYING) { + enif_mutex_lock(r->monv[mix].lock); + if (memcmp(mon, &r->monv[mix].mon, sizeof(*mon)) == 0) { + assert(r->monv[mix].state >= MON_ACTIVE); + r->monv[mix].state = MON_FREE_DOWN; + enif_mutex_unlock(r->monv[mix].lock); + return; + } + enif_mutex_unlock(r->monv[mix].lock); + } + } + enif_fprintf(stderr, "DOWN called for unknown monitor\n"); + abort(); +} + + + static ErlNifFunc nif_funcs[] = { {"lib_version", 0, lib_version}, @@ -2318,7 +2850,11 @@ static ErlNifFunc nif_funcs[] = {"write_nif", 2, write_nif}, {"read_nif", 2, read_nif}, {"is_closed_nif", 1, is_closed_nif}, - {"last_fd_stop_call", 0, last_fd_stop_call} + {"last_fd_stop_call", 0, last_fd_stop_call}, + {"alloc_monitor_resource_nif", 0, alloc_monitor_resource_nif}, + {"monitor_process_nif", 4, monitor_process_nif}, + {"demonitor_process_nif", 2, demonitor_process_nif}, + {"monitor_frenzy_nif", 4, monitor_frenzy_nif} }; ERL_NIF_INIT(nif_SUITE,nif_funcs,load,NULL,upgrade,unload) diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.c b/erts/emulator/test/nif_SUITE_data/nif_mod.c index e6106b6036..04699d3327 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_mod.c +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.c @@ -176,6 +176,7 @@ static void do_load_info(ErlNifEnv* env, ERL_NIF_TERM load_info, int* retvalp) CHECK(enif_is_empty_list(env, head)); } +#if NIF_LIB_VER != 3 static int load(ErlNifEnv* env, void** priv, ERL_NIF_TERM load_info) { NifModPrivData* data; @@ -230,6 +231,7 @@ static void unload(ErlNifEnv* env, void* priv) add_call(env, data, "unload"); NifModPrivData_release(data); } +#endif /* NIF_LIB_VER != 3 */ static ERL_NIF_TERM lib_version(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { -- cgit v1.2.3 From d85e74e0c0e4bc66c875e2fd5f54d89255df0047 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 9 Feb 2017 15:23:11 +0100 Subject: erts: Add pid argument to enif_select --- erts/emulator/test/nif_SUITE.erl | 54 +++++++++++++++++---------- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 16 ++++++-- 2 files changed, 47 insertions(+), 23 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index e3af9f7454..de26e73c3d 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -468,21 +468,31 @@ select(Config) when is_list(Config) -> ensure_lib_loaded(Config), Ref = make_ref(), + Ref2 = make_ref(), {{R, R_ptr}, {W, W_ptr}} = pipe_nif(), ok = write_nif(W, <<"hej">>), <<"hej">> = read_nif(R, 3), %% Wait for read eagain = read_nif(R, 3), - 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,Ref), + 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,null,Ref), [] = flush(), ok = write_nif(W, <<"hej">>), [{select, R, Ref, ready_input}] = flush(), + 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,self(),Ref2), + [{select, R, Ref2, ready_input}] = flush(), + Papa = self(), + Pid = spawn_link(fun() -> + [{select, R, Ref, ready_input}] = flush(), + Papa ! {self(), done} + end), + 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,Pid,Ref), + {Pid, done} = receive_any(1000), <<"hej">> = read_nif(R, 3), %% Wait for write Written = write_full(W, $a), - 0 = select_nif(W,?ERL_NIF_SELECT_WRITE,W,Ref), + 0 = select_nif(W,?ERL_NIF_SELECT_WRITE,W,self(),Ref), [] = flush(), Half = byte_size(Written) div 2, <> = Written, @@ -494,16 +504,16 @@ select(Config) when is_list(Config) -> %% Close write and wait for EOF eagain = read_nif(R, 1), - check_stop_ret(select_nif(W,?ERL_NIF_SELECT_STOP,W,Ref)), + check_stop_ret(select_nif(W,?ERL_NIF_SELECT_STOP,W,null,Ref)), [{fd_resource_stop, W_ptr, _}] = flush(), {1, {W_ptr,_}} = last_fd_stop_call(), true = is_closed_nif(W), [] = flush(), - 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,Ref), + 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,self(),Ref), [{select, R, Ref, ready_input}] = flush(), eof = read_nif(R,1), - check_stop_ret(select_nif(R,?ERL_NIF_SELECT_STOP,R,Ref)), + check_stop_ret(select_nif(R,?ERL_NIF_SELECT_STOP,R,null,Ref)), [{fd_resource_stop, R_ptr, _}] = flush(), {1, {R_ptr,_}} = last_fd_stop_call(), true = is_closed_nif(R), @@ -520,8 +530,8 @@ select_2(Config) -> %% Change ref eagain = read_nif(R, 1), - 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,Ref1), - 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,Ref2), + 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,null,Ref1), + 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,self(),Ref2), [] = flush(), ok = write_nif(W, <<"hej">>), @@ -530,35 +540,35 @@ select_2(Config) -> %% Change pid eagain = read_nif(R, 1), - 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,Ref1), + 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,null,Ref1), Papa = self(), - Pid2 = spawn_link(fun() -> - 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,Ref1), - [] = flush(), - Papa ! sync, - [{select, R, Ref1, ready_input}] = flush(), - <<"hej">> = read_nif(R, 3), - Papa ! done - end), + spawn_link(fun() -> + 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,null,Ref1), + [] = flush(), + Papa ! sync, + [{select, R, Ref1, ready_input}] = flush(), + <<"hej">> = read_nif(R, 3), + Papa ! done + end), sync = receive_any(), ok = write_nif(W, <<"hej">>), done = receive_any(), [] = flush(), - check_stop_ret(select_nif(R,?ERL_NIF_SELECT_STOP,R,Ref1)), + check_stop_ret(select_nif(R,?ERL_NIF_SELECT_STOP,R,null,Ref1)), [{fd_resource_stop, R_ptr, _}] = flush(), {1, {R_ptr,_}} = last_fd_stop_call(), true = is_closed_nif(R), %% Stop without previous read/write select - ?ERL_NIF_SELECT_STOP_CALLED = select_nif(W,?ERL_NIF_SELECT_STOP,W,Ref1), + ?ERL_NIF_SELECT_STOP_CALLED = select_nif(W,?ERL_NIF_SELECT_STOP,W,null,Ref1), [{fd_resource_stop, W_ptr, 1}] = flush(), {1, {W_ptr,1}} = last_fd_stop_call(), true = is_closed_nif(W), select_3(Config). -select_3(Config) -> +select_3(_Config) -> erlang:garbage_collect(), {_,_,2} = last_resource_dtor_call(), ok. @@ -2263,6 +2273,10 @@ call(Pid,Cmd) -> receive_any() -> receive M -> M end. +receive_any(Timeout) -> + receive M -> M + after Timeout -> timeout end. + flush() -> flush(10). flush(Timeout) -> @@ -2635,7 +2649,7 @@ term_to_binary_nif(_, _) -> ?nif_stub. binary_to_term_nif(_, _, _) -> ?nif_stub. port_command_nif(_, _) -> ?nif_stub. format_term_nif(_,_) -> ?nif_stub. -select_nif(_,_,_,_) -> ?nif_stub. +select_nif(_,_,_,_,_) -> ?nif_stub. pipe_nif() -> ?nif_stub. write_nif(_,_) -> ?nif_stub. read_nif(_,_) -> ?nif_stub. diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index ee925512d2..6cf02c6efe 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -75,6 +75,7 @@ static ERL_NIF_TERM atom_init; static ERL_NIF_TERM atom_stats; static ERL_NIF_TERM atom_done; static ERL_NIF_TERM atom_stop; +static ERL_NIF_TERM atom_null; typedef struct { @@ -242,6 +243,7 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_stats = enif_make_atom(env,"stats"); atom_done = enif_make_atom(env,"done"); atom_stop = enif_make_atom(env,"stop"); + atom_null = enif_make_atom(env,"null"); *priv_data = data; return 0; @@ -2119,6 +2121,7 @@ static ERL_NIF_TERM select_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv struct fd_resource* fdr; enum ErlNifSelectFlags mode; void* obj; + ErlNifPid nifpid, *pid = NULL; ERL_NIF_TERM ref; enum ErlNifSelectReturn retval; @@ -2129,11 +2132,16 @@ static ERL_NIF_TERM select_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv return enif_make_badarg(env); } - ref = argv[3]; + if (argv[3] != atom_null) { + if (!enif_get_local_pid(env, argv[3], &nifpid)) + return enif_make_badarg(env); + pid = &nifpid; + } + ref = argv[4]; fdr->was_selected = 1; enif_self(env, &fdr->pid); - retval = enif_select(env, fdr->fd, mode, obj, ref); + retval = enif_select(env, fdr->fd, mode, obj, pid, ref); return enif_make_int(env, (int)retval); } @@ -2160,7 +2168,9 @@ static ERL_NIF_TERM pipe_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] read_rsrc = enif_alloc_resource(fd_resource_type, sizeof(struct fd_resource)); write_rsrc = enif_alloc_resource(fd_resource_type, sizeof(struct fd_resource)); read_rsrc->fd = fds[0]; + read_rsrc->was_selected = 0; write_rsrc->fd = fds[1]; + write_rsrc->was_selected = 0; read_fd = enif_make_resource(env, read_rsrc); write_fd = enif_make_resource(env, write_rsrc); enif_release_resource(read_rsrc); @@ -2845,7 +2855,7 @@ static ErlNifFunc nif_funcs[] = {"binary_to_term_nif", 3, binary_to_term}, {"port_command_nif", 2, port_command}, {"format_term_nif", 2, format_term}, - {"select_nif", 4, select_nif}, + {"select_nif", 5, select_nif}, {"pipe_nif", 0, pipe_nif}, {"write_nif", 2, write_nif}, {"read_nif", 2, read_nif}, -- cgit v1.2.3 From a8d5234c77634df9522727ff200cef4fcab49c22 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 9 Feb 2017 17:30:30 +0100 Subject: erts: Change return value for enif_select to negative int as error and positive as success. --- erts/emulator/test/nif_SUITE.erl | 9 ++++----- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index de26e73c3d..d88ac01e46 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -457,11 +457,10 @@ t_on_load(Config) when is_list(Config) -> -define(ERL_NIF_SELECT_WRITE, (1 bsl 1)). -define(ERL_NIF_SELECT_STOP, (1 bsl 2)). --define(ERL_NIF_SELECT_ERROR, (1 bsl 0)). --define(ERL_NIF_SELECT_STOP_CALLED, (1 bsl 1)). --define(ERL_NIF_SELECT_STOP_SCHEDULED, (1 bsl 2)). --define(ERL_NIF_SELECT_INVALID_EVENT, (1 bsl 3)). --define(ERL_NIF_SELECT_FAILED, (1 bsl 4)). +-define(ERL_NIF_SELECT_STOP_CALLED, (1 bsl 0)). +-define(ERL_NIF_SELECT_STOP_SCHEDULED, (1 bsl 1)). +-define(ERL_NIF_SELECT_INVALID_EVENT, (1 bsl 2)). +-define(ERL_NIF_SELECT_FAILED, (1 bsl 3)). select(Config) when is_list(Config) -> diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 6cf02c6efe..05b4b05e16 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -2123,7 +2123,7 @@ static ERL_NIF_TERM select_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv void* obj; ErlNifPid nifpid, *pid = NULL; ERL_NIF_TERM ref; - enum ErlNifSelectReturn retval; + int retval; if (!get_fd(env, argv[0], &fdr) || !enif_get_uint(env, argv[1], &mode) @@ -2143,7 +2143,7 @@ static ERL_NIF_TERM select_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv enif_self(env, &fdr->pid); retval = enif_select(env, fdr->fd, mode, obj, pid, ref); - return enif_make_int(env, (int)retval); + return enif_make_int(env, retval); } static ERL_NIF_TERM pipe_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From 7c06ca6231b812965305522284dd9f2653ced98d Mon Sep 17 00:00:00 2001 From: Andrew Dryga Date: Tue, 14 Feb 2017 11:30:41 +0200 Subject: Fixed typos in erts --- erts/emulator/test/binary_SUITE.erl | 2 +- erts/emulator/test/bs_match_int_SUITE.erl | 2 +- erts/emulator/test/call_trace_SUITE.erl | 2 +- erts/emulator/test/ddll_SUITE.erl | 2 +- erts/emulator/test/dirty_nif_SUITE.erl | 2 +- erts/emulator/test/estone_SUITE.erl | 2 +- erts/emulator/test/float_SUITE.erl | 2 +- erts/emulator/test/hibernate_SUITE.erl | 2 +- erts/emulator/test/match_spec_SUITE.erl | 2 +- erts/emulator/test/node_container_SUITE.erl | 2 +- erts/emulator/test/num_bif_SUITE.erl | 2 +- erts/emulator/test/port_SUITE.erl | 2 +- erts/emulator/test/port_SUITE_data/port_test.c | 2 +- erts/emulator/test/port_bif_SUITE_data/port_test.c | 2 +- erts/emulator/test/system_info_SUITE.erl | 2 +- erts/emulator/test/time_SUITE.erl | 2 +- erts/emulator/test/z_SUITE.erl | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl index 238a8aa42d..324730d562 100644 --- a/erts/emulator/test/binary_SUITE.erl +++ b/erts/emulator/test/binary_SUITE.erl @@ -1008,7 +1008,7 @@ ordering(Config) when is_list(Config) -> ok. -%% Test that comparisions between binaries with different alignment work. +%% Test that comparison between binaries with different alignment work. unaligned_order(Config) when is_list(Config) -> L = lists:seq(0, 7), [test_unaligned_order(I, J) || I <- L, J <- L], diff --git a/erts/emulator/test/bs_match_int_SUITE.erl b/erts/emulator/test/bs_match_int_SUITE.erl index a7bd4b8ac3..32bfa2f1fa 100644 --- a/erts/emulator/test/bs_match_int_SUITE.erl +++ b/erts/emulator/test/bs_match_int_SUITE.erl @@ -247,7 +247,7 @@ match_huge_int(Config) when is_list(Config) -> 8 -> %% An attempt will be made to allocate heap space for %% the bignum (which will probably fail); only if the - %% allocation succeds will the matching fail because + %% allocation succeeds will the matching fail because %% the binary is too small. ok end, diff --git a/erts/emulator/test/call_trace_SUITE.erl b/erts/emulator/test/call_trace_SUITE.erl index 2e303ba9a8..e74631e916 100644 --- a/erts/emulator/test/call_trace_SUITE.erl +++ b/erts/emulator/test/call_trace_SUITE.erl @@ -233,7 +233,7 @@ basic() -> trace_func({'_','_','_'}, false), [b,a] = lists:reverse([a,b]), - %% Read out the remaing trace messages. + %% Read out the remaining trace messages. ?MODULE:expect({trace,Self,call,{lists,seq,[1,10]}}), ?MODULE:expect({trace,Self,call,{erlang,list_to_integer,["777"]}}), diff --git a/erts/emulator/test/ddll_SUITE.erl b/erts/emulator/test/ddll_SUITE.erl index 93b6f2d956..e7e518f82b 100644 --- a/erts/emulator/test/ddll_SUITE.erl +++ b/erts/emulator/test/ddll_SUITE.erl @@ -805,7 +805,7 @@ reference_count(Config) when is_list(Config) -> Pid1 ! {self(), die}, test_server:sleep(200), % Give time to unload. - % Verify that the driver was automaticly unloaded when the + % Verify that the driver was automatically unloaded when the % process died. {error, not_loaded}=erl_ddll:unload_driver(echo_drv), ok. diff --git a/erts/emulator/test/dirty_nif_SUITE.erl b/erts/emulator/test/dirty_nif_SUITE.erl index 991ba0acc8..5ba0d85ff3 100644 --- a/erts/emulator/test/dirty_nif_SUITE.erl +++ b/erts/emulator/test/dirty_nif_SUITE.erl @@ -214,7 +214,7 @@ dirty_call_while_terminated(Config) when is_list(Config) -> undefined = process_info(Dirty, status), false = erlang:is_process_alive(Dirty), false = lists:member(Dirty, processes()), - %% Binary still refered by Dirty process not yet cleaned up + %% Binary still referred by Dirty process not yet cleaned up %% since the dirty nif has not yet returned... {value, {BinAddr, 4711, 2}} = lists:keysearch(4711, 2, element(2, diff --git a/erts/emulator/test/estone_SUITE.erl b/erts/emulator/test/estone_SUITE.erl index 3ce849b88e..35f695ffe5 100644 --- a/erts/emulator/test/estone_SUITE.erl +++ b/erts/emulator/test/estone_SUITE.erl @@ -708,7 +708,7 @@ alloc(I) -> %% Time to call bif's %% Lot's of element stuff which reflects the record code which -%% is becomming more and more common +%% is becoming more and more common bif_dispatch(0) -> 0; bif_dispatch(I) -> diff --git a/erts/emulator/test/float_SUITE.erl b/erts/emulator/test/float_SUITE.erl index 36b1f9179f..ad33ad705b 100644 --- a/erts/emulator/test/float_SUITE.erl +++ b/erts/emulator/test/float_SUITE.erl @@ -208,7 +208,7 @@ span_cmp(Axis, Incr, Length) -> %% for both negative and positive numbers. %% %% Axis: The number around which to do the tests eg. (1 bsl 58) - 1.0 -%% Incr: How much to increment the test numbers inbetween each test. +%% Incr: How much to increment the test numbers in-between each test. %% Length: Length/2 is the number of Incr away from Axis to test on the %% negative and positive plane. %% Diff: How much the float and int should differ when comparing diff --git a/erts/emulator/test/hibernate_SUITE.erl b/erts/emulator/test/hibernate_SUITE.erl index 6f8ce02266..90693595a7 100644 --- a/erts/emulator/test/hibernate_SUITE.erl +++ b/erts/emulator/test/hibernate_SUITE.erl @@ -349,7 +349,7 @@ clean_dict() -> lists:foreach(fun ({Key, _}) -> erase(Key) end, Dict). %% -%% Wake up and then immediatly bif trap with a lengthy computation. +%% Wake up and then immediately bif trap with a lengthy computation. %% wake_up_and_bif_trap(Config) when is_list(Config) -> diff --git a/erts/emulator/test/match_spec_SUITE.erl b/erts/emulator/test/match_spec_SUITE.erl index 34e956bc21..971a047309 100644 --- a/erts/emulator/test/match_spec_SUITE.erl +++ b/erts/emulator/test/match_spec_SUITE.erl @@ -646,7 +646,7 @@ destructive_in_test_bif(Config) when is_list(Config) -> ([],[{'_',[],[{message,{get_tcw}}]}],trace), ok. -%% Test that the comparision between boxed and small does not crash emulator +%% Test that the comparison between boxed and small does not crash emulator boxed_and_small(Config) when is_list(Config) -> {ok, Node} = start_node(match_spec_suite_other), ok = rpc:call(Node,?MODULE,do_boxed_and_small,[]), diff --git a/erts/emulator/test/node_container_SUITE.erl b/erts/emulator/test/node_container_SUITE.erl index 7356f31b75..291d3ee30d 100644 --- a/erts/emulator/test/node_container_SUITE.erl +++ b/erts/emulator/test/node_container_SUITE.erl @@ -153,7 +153,7 @@ ttbtteq_do_remote(RNode) -> %% %% Test case: round_trip_eq %% -%% Tests that node containers that are sent beteen nodes stay equal to themselves. +%% Tests that node containers that are sent between nodes stay equal to themselves. round_trip_eq(Config) when is_list(Config) -> ThisNode = {node(), erlang:system_info(creation)}, NodeFirstName = get_nodefirstname(), diff --git a/erts/emulator/test/num_bif_SUITE.erl b/erts/emulator/test/num_bif_SUITE.erl index 1a1ab0e5e0..8016a21424 100644 --- a/erts/emulator/test/num_bif_SUITE.erl +++ b/erts/emulator/test/num_bif_SUITE.erl @@ -108,7 +108,7 @@ t_float(Config) when is_list(Config) -> 4294967305.0 = float(id(4294967305)), -4294967305.0 = float(id(-4294967305)), - %% Extremly big bignums. + %% Extremely big bignums. Big = id(list_to_integer(id(lists:duplicate(2000, $1)))), {'EXIT', {badarg, _}} = (catch float(Big)), diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index 2a13b2d2f4..c117554f90 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -2131,7 +2131,7 @@ ping(Config, Sizes, HSize, CmdLine, Options) -> %% Sizes = Size of packets to generated. %% HSize = Header size: 1, 2, or 4 %% CmdLine = Additional command line options. -%% Options = Addtional port options. +%% Options = Additional port options. expect_input(Config, Sizes, HSize, CmdLine, Options) -> expect_input1(Config, Sizes, {HSize, CmdLine, Options}, [], []). diff --git a/erts/emulator/test/port_SUITE_data/port_test.c b/erts/emulator/test/port_SUITE_data/port_test.c index e199a0fc13..fa97b4c9d0 100644 --- a/erts/emulator/test/port_SUITE_data/port_test.c +++ b/erts/emulator/test/port_SUITE_data/port_test.c @@ -41,7 +41,7 @@ extern int errno; typedef struct { char* progname; /* Name of this program (from argv[0]). */ int header_size; /* Number of bytes in each packet header: - * 1, 2, or 4, or 0 for a continous byte stream. */ + * 1, 2, or 4, or 0 for a continuous byte stream. */ int fd_from_erl; /* File descriptor from Erlang. */ int fd_to_erl; /* File descriptor to Erlang. */ unsigned char* io_buf; /* Buffer for file i/o. */ diff --git a/erts/emulator/test/port_bif_SUITE_data/port_test.c b/erts/emulator/test/port_bif_SUITE_data/port_test.c index 28324a56a6..923ab99ccc 100644 --- a/erts/emulator/test/port_bif_SUITE_data/port_test.c +++ b/erts/emulator/test/port_bif_SUITE_data/port_test.c @@ -39,7 +39,7 @@ extern int errno; typedef struct { char* progname; /* Name of this program (from argv[0]). */ int header_size; /* Number of bytes in each packet header: - * 1, 2, or 4, or 0 for a continous byte stream. */ + * 1, 2, or 4, or 0 for a continuous byte stream. */ int fd_from_erl; /* File descriptor from Erlang. */ int fd_to_erl; /* File descriptor to Erlang. */ unsigned char* io_buf; /* Buffer for file i/o. */ diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl index 6a772bf7c9..6bd1eb1e1e 100644 --- a/erts/emulator/test/system_info_SUITE.erl +++ b/erts/emulator/test/system_info_SUITE.erl @@ -174,7 +174,7 @@ memory(Config) when is_list(Config) -> %% erts_debug:set_internal_state(available_internal_state, true), - %% Use a large heap size on the controling process in + %% Use a large heap size on the controlling process in %% order to avoid changes in its heap size during %% comparisons. MinHeapSize = process_flag(min_heap_size, 1024*1024), diff --git a/erts/emulator/test/time_SUITE.erl b/erts/emulator/test/time_SUITE.erl index 9501569814..c13d03bcc4 100644 --- a/erts/emulator/test/time_SUITE.erl +++ b/erts/emulator/test/time_SUITE.erl @@ -132,7 +132,7 @@ local_to_univ_utc(Config) when is_list(Config) -> end. -%% Tests conversion from univeral to local time. +%% Tests conversion from universal to local time. univ_to_local(Config) when is_list(Config) -> test_univ_to_local(test_data()). diff --git a/erts/emulator/test/z_SUITE.erl b/erts/emulator/test/z_SUITE.erl index d663cc548c..a90701c5d2 100644 --- a/erts/emulator/test/z_SUITE.erl +++ b/erts/emulator/test/z_SUITE.erl @@ -226,7 +226,7 @@ pollset_size(Config) when is_list(Config) -> "Pollset size information not available"} end; false -> - %% Somtimes we have fewer descriptors in the + %% Sometimes we have fewer descriptors in the %% pollset at the end than when we started, but %% that is ok as long as there are at least 2 %% descriptors (dist listen socket and -- cgit v1.2.3 From d73423cdba178c166f25e00a4608ccc8d0465937 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 14 Feb 2017 15:53:04 +0100 Subject: erts: Fix round/1 for large floats 1> round(6209607916799025.0). 6209607916799026 Problem: Adding/subtracting 0.5 and large double floats between (1 bsl 52) and (1 bsl 53) does not give reliable results. Solution: Use round() function in math.h. --- erts/emulator/test/guard_SUITE.erl | 1 + erts/emulator/test/num_bif_SUITE.erl | 3 +++ 2 files changed, 4 insertions(+) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/guard_SUITE.erl b/erts/emulator/test/guard_SUITE.erl index e155e5f49f..54ee710363 100644 --- a/erts/emulator/test/guard_SUITE.erl +++ b/erts/emulator/test/guard_SUITE.erl @@ -317,6 +317,7 @@ guard_bifs(Config) when is_list(Config) -> try_gbif('float/1', Big, float(id(Big))), try_gbif('trunc/1', Float, 387924.0), try_gbif('round/1', Float, 387925.0), + try_gbif('round/1', 6209607916799025.0, 6209607916799025), try_gbif('length/1', [], 0), try_gbif('length/1', [a], 1), diff --git a/erts/emulator/test/num_bif_SUITE.erl b/erts/emulator/test/num_bif_SUITE.erl index d1c9648017..bb85738454 100644 --- a/erts/emulator/test/num_bif_SUITE.erl +++ b/erts/emulator/test/num_bif_SUITE.erl @@ -293,6 +293,9 @@ t_round(Config) when is_list(Config) -> 4294967297 = round(id(4294967296.9)), -4294967296 = -round(id(4294967296.1)), -4294967297 = -round(id(4294967296.9)), + + 6209607916799025 = round(id(6209607916799025.0)), + -6209607916799025 = round(id(-6209607916799025.0)), ok. t_trunc(Config) when is_list(Config) -> -- cgit v1.2.3 From 0a144d1fc4bebefcc74b0cb63fe76809bc041789 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Fri, 17 Feb 2017 15:26:01 +0100 Subject: Ensure prim_eval:'receive' wont clobber def_arg_reg[0] def_arg_reg[0] is used for storage of timeout instruction when a 'receive after' is executed. When a process was scheduled out inside prim_eval:'receive'/0 due to a function call, def_arg_reg[0] was overwritten due to storage of live registers. prim_eval:'receive'/2 now calls arg_reg_alloc/0 which bumps all reductions and then calls arg_reg_alloc/7 which will cause an allocation of a new arg_reg array since def_arg_reg only can hold 6 values. This ensures that the timeout instruction in def_arg_reg[0] used for the timeout wont be overwritten. --- erts/emulator/test/Makefile | 1 + erts/emulator/test/prim_eval_SUITE.erl | 78 ++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 erts/emulator/test/prim_eval_SUITE.erl (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index 2e48c475d5..453f819d1b 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -87,6 +87,7 @@ MODULES= \ op_SUITE \ port_SUITE \ port_bif_SUITE \ + prim_eval_SUITE \ process_SUITE \ pseudoknot_SUITE \ receive_SUITE \ diff --git a/erts/emulator/test/prim_eval_SUITE.erl b/erts/emulator/test/prim_eval_SUITE.erl new file mode 100644 index 0000000000..3f4965f96d --- /dev/null +++ b/erts/emulator/test/prim_eval_SUITE.erl @@ -0,0 +1,78 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2017. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +-module(prim_eval_SUITE). +-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, + init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2]). + +-export(['ERL-365'/1]). + +init_per_testcase(_Case, Config) -> + Config. + +end_per_testcase(_Case, _Config) -> + ok. + +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. + +groups() -> + []. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +all() -> + ['ERL-365']. + +'ERL-365'(Config) when is_list(Config) -> + %% def_arg_reg[0] is used for storage of timeout instruction + %% when a 'receive after' is executed. When a process was + %% scheduled out inside prim_eval:'receive'/0 due to a function + %% call, def_arg_reg[0] was overwritten due to storage of live + %% registers. + P = spawn_link(fun () -> + prim_eval:'receive'(fun (_M) -> + erlang:bump_reductions((1 bsl 27)-1), + id(true), + nomatch + end, + 200) + end), + receive after 100 -> ok end, + P ! {wont, match}, + receive after 200 -> ok end, + ok. + + + +id(X) -> + X. -- cgit v1.2.3 From 5adbf961a3c79a6782f8be8336ec26594754e9e8 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 20 Feb 2017 19:16:48 +0100 Subject: erts: Add enif_compare_monitors # Conflicts: # erts/emulator/test/nif_SUITE_data/nif_SUITE.c --- erts/emulator/test/nif_SUITE.erl | 11 +++++++---- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index d88ac01e46..9932b526b9 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -598,10 +598,11 @@ monitor_process_a(Config) -> end end), R_ptr = alloc_monitor_resource_nif(), - {0, Mon} = monitor_process_nif(R_ptr, Pid, UseMsgEnv, self()), + {0, Mon1} = monitor_process_nif(R_ptr, Pid, UseMsgEnv, self()), [R_ptr] = monitored_by(Pid), Terminator(Pid), - [{monitor_resource_down, R_ptr, Pid, Mon}] = flush(), + [{monitor_resource_down, R_ptr, Pid, Mon2}] = flush(), + 0 = compare_monitors_nif(Mon1, Mon2), [] = last_resource_dtor_call(), ok = release_resource(R_ptr), {R_ptr, _, 1} = last_resource_dtor_call() @@ -650,8 +651,9 @@ monitor_process_c(Config) -> Papa ! {self(), done, R_ptr, Mon}, exit end), - [{Pid, done, R_ptr, Mon}, - {monitor_resource_down, R_ptr, Pid, Mon}] = flush(), + [{Pid, done, R_ptr, Mon1}, + {monitor_resource_down, R_ptr, Pid, Mon2}] = flush(), + compare_monitors_nif(Mon1, Mon2), {R_ptr, _, 1} = last_resource_dtor_call(), ok. @@ -2657,6 +2659,7 @@ last_fd_stop_call() -> ?nif_stub. alloc_monitor_resource_nif() -> ?nif_stub. monitor_process_nif(_,_,_,_) -> ?nif_stub. demonitor_process_nif(_,_) -> ?nif_stub. +compare_monitors_nif(_,_) -> ?nif_stub. monitor_frenzy_nif(_,_,_,_) -> ?nif_stub. %% maps diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 05b4b05e16..a9622e3b8d 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -2407,6 +2407,18 @@ static ERL_NIF_TERM demonitor_process_nif(ErlNifEnv* env, int argc, const ERL_NI return enif_make_int(env, res); } +static ERL_NIF_TERM compare_monitors_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ErlNifMonitor m1, m2; + if (!get_monitor(env, argv[0], &m1) + || !get_monitor(env, argv[1], &m2)) { + return enif_make_badarg(env); + } + + return enif_make_int(env, enif_compare_monitors(&m1, &m2)); +} + + /*********** monitor_frenzy ************/ struct frenzy_rand_bits @@ -2763,7 +2775,7 @@ static void frenzy_resource_down(ErlNifEnv* env, void* obj, ErlNifPid* pid, for (mix = 0; mix < FRENZY_MONITORS_MAX; mix++) { if (r->monv[mix].pid.pid == pid->pid && r->monv[mix].state >= MON_TRYING) { enif_mutex_lock(r->monv[mix].lock); - if (memcmp(mon, &r->monv[mix].mon, sizeof(*mon)) == 0) { + if (enif_compare_monitors(mon, &r->monv[mix].mon) == 0) { assert(r->monv[mix].state >= MON_ACTIVE); r->monv[mix].state = MON_FREE_DOWN; enif_mutex_unlock(r->monv[mix].lock); @@ -2864,6 +2876,7 @@ static ErlNifFunc nif_funcs[] = {"alloc_monitor_resource_nif", 0, alloc_monitor_resource_nif}, {"monitor_process_nif", 4, monitor_process_nif}, {"demonitor_process_nif", 2, demonitor_process_nif}, + {"compare_monitors_nif", 2, compare_monitors_nif}, {"monitor_frenzy_nif", 4, monitor_frenzy_nif} }; -- cgit v1.2.3 From 68ad03bc3661f4bf82afbbde65a8d04861a6f799 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 13 Feb 2017 18:40:32 +0100 Subject: Expand nif_SUITE:monitor_frenzy with binary_to_term to provoke resource revival race. --- erts/emulator/test/nif_SUITE.erl | 32 +++++++++++++++++++-------- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 29 ++++++++++++++---------- 2 files changed, 40 insertions(+), 21 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 5857ed51e4..d29537e3ef 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -720,6 +720,8 @@ monitored_by(Pid) -> -define(FRENZY_RAND_BITS, 25). +%% Exercise monitoring from NIF resources by randomly +%% create/destruct processes, resources and monitors. monitor_frenzy(Config) -> ensure_lib_loaded(Config), @@ -731,7 +733,7 @@ monitor_frenzy(Config) -> spawn_link(fun() -> SelfPix = monitor_frenzy_nif(init, ?FRENZY_RAND_BITS, 0, 0), unlink(Master), - frenzy(SelfPix, undefined) + frenzy(SelfPix, {undefined, []}) end), receive after 5*1000 -> ok end, @@ -757,7 +759,7 @@ frenzy(SelfPix, State0) -> State1 = frenzy_do_op(SelfPix, Op, (Rnd bsr 2), State0), frenzy(SelfPix, State1). -frenzy_do_op(SelfPix, Op, Rnd, Pid0) -> +frenzy_do_op(SelfPix, Op, Rnd, {Pid0,RBins}=State0) -> case Op of 0 -> % add/remove process Papa = self(), @@ -778,24 +780,36 @@ frenzy_do_op(SelfPix, Op, Rnd, Pid0) -> end, case monitor_frenzy_nif(Op, Rnd, SelfPix, NewPid) of NewPix when is_integer(NewPix) -> - NewPid ! {go, NewPix, undefined}, - undefined; + NewPid ! {go, NewPix, {undefined, []}}, + {undefined, RBins}; ExitPid when is_pid(ExitPid) -> false = (ExitPid =:= self()), exit(ExitPid,die), - NewPid; + {NewPid, RBins}; done -> done end; + + 3 -> + %% Try provoke revival-race of resource from magic ref external format + _ = [binary_to_term(B) || B <- RBins], + {Pid0, []}; _ -> case monitor_frenzy_nif(Op, Rnd, SelfPix, undefined) of - ok -> Pid0; - 0 -> Pid0; - 1 -> Pid0; + Rsrc when ?is_resource(Rsrc) -> + %% Store resource in ext format only, for later revival + State1 = {Pid0, [term_to_binary(Rsrc) | RBins]}, + gc_and_return(State1); + ok -> State0; + 0 -> State0; + 1 -> State0; done -> done end end. +gc_and_return(RetVal) -> + erlang:garbage_collect(), + RetVal. hipe(Config) when is_list(Config) -> Data = proplists:get_value(data_dir, Config), @@ -1171,7 +1185,7 @@ resource_new_do2(Type) -> ResB = make_new_resource(Type, BinB), true = is_reference(ResA), true = is_reference(ResB), - ResA /= ResB, + true = (ResA /= ResB), {PtrA,BinA} = get_resource(Type, ResA), {PtrB,BinB} = get_resource(Type, ResB), true = (PtrA =/= PtrB), diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index d5dd379d76..97cb7e55d6 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -2669,19 +2669,24 @@ static ERL_NIF_TERM monitor_frenzy_nif(ErlNifEnv* env, int argc, const ERL_NIF_T } DBG_TRACE2("New resource at r=%p rix=%u\n", r, rix); } - else if (rand_bits(&rnd, 3) == 0) { + else { + unsigned int resource_op = rand_bits(&rnd, 3); r = resv[rix].obj; - resv[rix].obj = NULL; - resv[rix].release_cnt++; - enif_mutex_unlock(resv[rix].lock); - DBG_TRACE2("Delete resource at r=%p rix=%u\n", r, rix); - enif_release_resource(r); - retval = atom_ok; - break; - } - else { - r = resv[rix].obj; - } + if (resource_op == 0) { + resv[rix].obj = NULL; + resv[rix].release_cnt++; + enif_mutex_unlock(resv[rix].lock); + DBG_TRACE2("Delete resource at r=%p rix=%u\n", r, rix); + enif_release_resource(r); + retval = atom_ok; + break; + } + else if (resource_op == 1) { + retval = enif_make_resource(env, r); + enif_mutex_unlock(resv[rix].lock); + break; + } + } enif_keep_resource(r); enif_mutex_unlock(resv[rix].lock); -- cgit v1.2.3 From 471a22dd081da31933c883afe686007793812075 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 13 Feb 2017 19:58:45 +0100 Subject: Expand nif_SUITE:monitor_frenzy to verify dtor calls --- erts/emulator/test/nif_SUITE.erl | 7 ++++- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 39 ++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 4 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index d29537e3ef..8439b28010 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -742,7 +742,12 @@ monitor_frenzy(Config) -> Pids = monitor_frenzy_nif(stop, 0, 0, 0), io:format("stats = ~p\n", [monitor_frenzy_nif(stats, 0, 0, 0)]), - lists:foreach(fun(P) -> exit(P, stop) end, Pids), + lists:foreach(fun(P) -> + MRef = monitor(process, P), + exit(P, stop), + {'DOWN', MRef, process, P, _} = receive_any() + end, + Pids), io:format("stats = ~p\n", [monitor_frenzy_nif(stats, 0, 0, 0)]), diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 97cb7e55d6..4f003d11f5 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -2484,9 +2484,11 @@ struct frenzy_resource { }; struct frenzy_reslot { ErlNifMutex* lock; + int stopped; struct frenzy_resource* obj; unsigned long alloc_cnt; unsigned long release_cnt; + unsigned long dtor_cnt; }; static struct frenzy_reslot resv[FRENZY_RESOURCES_MAX]; @@ -2536,8 +2538,10 @@ static ERL_NIF_TERM monitor_frenzy_nif(ErlNifEnv* env, int argc, const ERL_NIF_T for (rix = 0; rix < FRENZY_RESOURCES_MAX; rix++) { resv[rix].lock = enif_mutex_create("nif_SUITE:monitor_frenzy.resv.lock"); resv[rix].obj = NULL; + resv[rix].stopped = 0; resv[rix].alloc_cnt = 0; resv[rix].release_cnt = 0; + resv[rix].dtor_cnt = 0; } /* Add self as first process */ @@ -2553,12 +2557,14 @@ static ERL_NIF_TERM monitor_frenzy_nif(ErlNifEnv* env, int argc, const ERL_NIF_T ERL_NIF_TERM hist[FRENZY_PROCS_MAX]; unsigned long res_alloc_cnt = 0; unsigned long res_release_cnt = 0; + unsigned long res_dtor_cnt = 0; for (ref_ix = 0; ref_ix < FRENZY_PROCS_MAX; ref_ix++) { hist[ref_ix] = enif_make_ulong(env, proc_histogram[ref_ix]); } for (rix = 0; rix < FRENZY_RESOURCES_MAX; rix++) { res_alloc_cnt += resv[rix].alloc_cnt; res_release_cnt += resv[rix].release_cnt; + res_dtor_cnt += resv[rix].dtor_cnt; } return @@ -2569,12 +2575,29 @@ static ERL_NIF_TERM monitor_frenzy_nif(ErlNifEnv* env, int argc, const ERL_NIF_T enif_make_ulong(env, spawn_cnt)), enif_make_tuple2(env, enif_make_string(env, "kill_cnt", ERL_NIF_LATIN1), enif_make_ulong(env, kill_cnt)), - enif_make_tuple3(env, enif_make_string(env, "resource_alloc", ERL_NIF_LATIN1), + enif_make_tuple4(env, enif_make_string(env, "resource_alloc", ERL_NIF_LATIN1), enif_make_ulong(env, res_alloc_cnt), - enif_make_ulong(env, res_release_cnt))); + enif_make_ulong(env, res_release_cnt), + enif_make_ulong(env, res_dtor_cnt))); } else if (Op == atom_stop && procs_lock) { /* stop all */ + + /* Release all resources */ + for (rix = 0; rix < FRENZY_RESOURCES_MAX; rix++) { + enif_mutex_lock(resv[rix].lock); + r = resv[rix].obj; + if (r) { + resv[rix].obj = NULL; + resv[rix].release_cnt++; + } + resv[rix].stopped = 1; + enif_mutex_unlock(resv[rix].lock); + if (r) + enif_release_resource(r); + } + + /* Remove and return all pids */ retval = enif_make_list(env, 0); enif_mutex_lock(procs_lock); for (ref_ix = 0; ref_ix < nprocs; ref_ix++) { @@ -2587,6 +2610,7 @@ static ERL_NIF_TERM monitor_frenzy_nif(ErlNifEnv* env, int argc, const ERL_NIF_T nprocs = 0; old_nprocs = 0; enif_mutex_unlock(procs_lock); + return retval; } return enif_make_badarg(env); @@ -2655,7 +2679,12 @@ static ERL_NIF_TERM monitor_frenzy_nif(ErlNifEnv* env, int argc, const ERL_NIF_T while (enif_mutex_trylock(resv[rix].lock) == EBUSY) { rix = (rix + inc) % FRENZY_RESOURCES_MAX; } - if (resv[rix].obj == NULL) { + if (resv[rix].stopped) { + retval = atom_done; + enif_mutex_unlock(resv[rix].lock); + break; + } + else if (resv[rix].obj == NULL) { r = enif_alloc_resource(frenzy_resource_type, sizeof(struct frenzy_resource)); resv[rix].obj = r; @@ -2779,6 +2808,10 @@ static void frenzy_resource_dtor(ErlNifEnv* env, void* obj) DBG_TRACE2("DTOR r=%p rix=%u\n", r, r->rix); + enif_mutex_lock(resv[r->rix].lock); + resv[r->rix].dtor_cnt++; + enif_mutex_unlock(resv[r->rix].lock); + for (mix = 0; mix < FRENZY_MONITORS_MAX; mix++) { assert(r->monv[mix].state != MON_PENDING); enif_mutex_destroy(r->monv[mix].lock); -- cgit v1.2.3 From 839ad04bbacb329c89568371bbf5a28d4b2bba25 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 14 Feb 2017 14:23:15 +0100 Subject: Fix whitebox monitor tests --- erts/emulator/test/erl_link_SUITE.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/erl_link_SUITE.erl b/erts/emulator/test/erl_link_SUITE.erl index 89e1aefb50..9258897764 100644 --- a/erts/emulator/test/erl_link_SUITE.erl +++ b/erts/emulator/test/erl_link_SUITE.erl @@ -60,7 +60,7 @@ % These are to be kept in sync with erl_monitors.h -define(MON_ORIGIN, 1). --define(MON_TARGET, 3). +-define(MON_TARGET, 2). -record(erl_link, {type = ?LINK_UNDEF, @@ -69,7 +69,7 @@ % This is to be kept in sync with erl_bif_info.c (make_monitor_list) --record(erl_monitor, {type, % MON_ORIGIN or MON_TARGET (1 or 3) +-record(erl_monitor, {type, % MON_ORIGIN or MON_TARGET ref, pid, % Process or nodename name = []}). % registered name or [] -- cgit v1.2.3 From d7abb5e2efc5dfd0f100b9a8978bc9e87e15cd2d Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 16 Feb 2017 14:42:24 +0100 Subject: erts: Skip nif_SUITE:select on windows for now... --- erts/emulator/test/nif_SUITE.erl | 7 +++++++ erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 15 ++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 8439b28010..c1d9632fb5 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -128,6 +128,13 @@ init_per_testcase(hipe, Config) -> undefined -> {skip, "HiPE is disabled"}; _ -> Config end; +init_per_testcase(select, Config) -> + case os:type() of + {win32,_} -> + {skip, "Test not yet implemented for windows"}; + _ -> + Config + end; init_per_testcase(_Case, Config) -> Config. diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 4f003d11f5..69c5f09bd5 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -23,10 +23,10 @@ #include #include #include +#include #ifndef __WIN32__ #include #include -#include #endif #include "nif_mod.h" @@ -143,7 +143,7 @@ static ErlNifResourceTypeInit fd_rt_init = { fd_resource_stop }; struct fd_resource { - int fd; + ErlNifEvent fd; int was_selected; ErlNifPid pid; }; @@ -2144,7 +2144,7 @@ static ERL_NIF_TERM select_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv int retval; if (!get_fd(env, argv[0], &fdr) - || !enif_get_uint(env, argv[1], &mode) + || !enif_get_uint(env, argv[1], (unsigned int*)&mode) || !enif_get_resource(env, argv[2], fd_resource_type, &obj)) { return enif_make_badarg(env); @@ -2164,6 +2164,7 @@ static ERL_NIF_TERM select_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv return enif_make_int(env, retval); } +#ifndef __WIN32__ static ERL_NIF_TERM pipe_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { struct fd_resource* read_rsrc; @@ -2274,15 +2275,21 @@ static ERL_NIF_TERM is_closed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a return fdr->fd < 0 ? atom_true : atom_false; } +#endif /* !__WIN32__ */ + static void fd_resource_dtor(ErlNifEnv* env, void* obj) { struct fd_resource* fdr = (struct fd_resource*)obj; resource_dtor(env, obj); +#ifdef __WIN32__ + abort(); +#else if (fdr->fd >= 0) { assert(!fdr->was_selected); close(fdr->fd); } +#endif } static struct { @@ -2924,10 +2931,12 @@ static ErlNifFunc nif_funcs[] = {"port_command_nif", 2, port_command}, {"format_term_nif", 2, format_term}, {"select_nif", 5, select_nif}, +#ifndef __WIN32__ {"pipe_nif", 0, pipe_nif}, {"write_nif", 2, write_nif}, {"read_nif", 2, read_nif}, {"is_closed_nif", 1, is_closed_nif}, +#endif {"last_fd_stop_call", 0, last_fd_stop_call}, {"alloc_monitor_resource_nif", 0, alloc_monitor_resource_nif}, {"monitor_process_nif", 4, monitor_process_nif}, -- cgit v1.2.3 From af7cf70ca22a34add7836963d086ca0764f4fbae Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 20 Feb 2017 20:20:29 +0100 Subject: Fix ErlNifMonitor handling --- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 69c5f09bd5..8fe5ee809a 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -2708,7 +2708,7 @@ static ERL_NIF_TERM monitor_frenzy_nif(ErlNifEnv* env, int argc, const ERL_NIF_T else { unsigned int resource_op = rand_bits(&rnd, 3); r = resv[rix].obj; - if (resource_op == 0) { + if (resource_op == 0) { /* delete resource */ resv[rix].obj = NULL; resv[rix].release_cnt++; enif_mutex_unlock(resv[rix].lock); @@ -2717,7 +2717,7 @@ static ERL_NIF_TERM monitor_frenzy_nif(ErlNifEnv* env, int argc, const ERL_NIF_T retval = atom_ok; break; } - else if (resource_op == 1) { + else if (resource_op == 1) { /* return resource */ retval = enif_make_resource(env, r); enif_mutex_unlock(resv[rix].lock); break; -- cgit v1.2.3 From 058800faf6b8fa4842aa0f8c3683cab26d399f60 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 22 Feb 2017 15:57:33 +0100 Subject: Fix nif_SUITE:select for old linux with pipe capacity equal to PIPE_BUF meaning pipe must be empty to be writable. --- erts/emulator/test/nif_SUITE.erl | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index c1d9632fb5..693db42e58 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -500,13 +500,8 @@ select(Config) when is_list(Config) -> Written = write_full(W, $a), 0 = select_nif(W,?ERL_NIF_SELECT_WRITE,W,self(),Ref), [] = flush(), - Half = byte_size(Written) div 2, - <> = Written, - First = read_nif(R,Half), + Written = read_nif(R,byte_size(Written)), [{select, W, Ref, ready_output}] = flush(), - Third = write_full(W, $A), - Half2 = byte_size(Second), - <> = read_nif(R, byte_size(Written)), %% Close write and wait for EOF eagain = read_nif(R, 1), -- cgit v1.2.3 From ec3d7602ca96819f23ab9bc59e370c6defc9cd8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 23 Feb 2017 11:50:05 +0100 Subject: erts: Test erts_internal:maps_to_list/2 --- erts/emulator/test/map_SUITE.erl | 66 ++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 16 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/map_SUITE.erl b/erts/emulator/test/map_SUITE.erl index dfa1629112..02f3c89318 100644 --- a/erts/emulator/test/map_SUITE.erl +++ b/erts/emulator/test/map_SUITE.erl @@ -52,6 +52,7 @@ t_bif_map_values/1, t_bif_map_to_list/1, t_bif_map_from_list/1, + t_bif_erts_internal_maps_to_list/1, %% erlang t_erlang_hash/1, @@ -118,6 +119,7 @@ all() -> [t_build_and_match_literals, t_build_and_match_literals_large, t_bif_map_update, t_bif_map_values, t_bif_map_to_list, t_bif_map_from_list, + t_bif_erts_internal_maps_to_list, %% erlang t_erlang_hash, t_map_encode_decode, @@ -2362,23 +2364,55 @@ t_bif_map_from_list(Config) when is_list(Config) -> {'EXIT', {badarg,_}} = (catch maps:from_list(id(42))), ok. -t_bif_build_and_check(Config) when is_list(Config) -> - ok = check_build_and_remove(750,[ - fun(K) -> [K,K] end, - fun(K) -> [float(K),K] end, - fun(K) -> K end, - fun(K) -> {1,K} end, - fun(K) -> {K} end, - fun(K) -> [K|K] end, - fun(K) -> [K,1,2,3,4] end, - fun(K) -> {K,atom} end, - fun(K) -> float(K) end, - fun(K) -> integer_to_list(K) end, - fun(K) -> list_to_atom(integer_to_list(K)) end, - fun(K) -> [K,{K,[K,{K,[K]}]}] end, - fun(K) -> <> end - ]), +t_bif_erts_internal_maps_to_list(Config) when is_list(Config) -> + %% small maps + [] = erts_internal:maps_to_list(#{},-1), + [] = erts_internal:maps_to_list(#{},-2), + [] = erts_internal:maps_to_list(#{},10), + [{a,1},{b,2}] = lists:sort(erts_internal:maps_to_list(#{a=>1,b=>2}, 2)), + [{a,1},{b,2}] = lists:sort(erts_internal:maps_to_list(#{a=>1,b=>2}, -1)), + [{_,_}] = erts_internal:maps_to_list(#{a=>1,b=>2}, 1), + [{a,1},{b,2},{c,3}] = lists:sort(erts_internal:maps_to_list(#{c=>3,a=>1,b=>2},-2)), + [{a,1},{b,2},{c,3}] = lists:sort(erts_internal:maps_to_list(#{c=>3,a=>1,b=>2},3)), + [{a,1},{b,2},{c,3}] = lists:sort(erts_internal:maps_to_list(#{c=>3,a=>1,b=>2},5)), + [{_,_},{_,_}] = erts_internal:maps_to_list(#{c=>3,a=>1,b=>2},2), + [{_,_}] = erts_internal:maps_to_list(#{c=>3,a=>1,b=>2},1), + [] = erts_internal:maps_to_list(#{c=>3,a=>1,b=>2},0), + + %% big maps + M = maps:from_list([{I,ok}||I <- lists:seq(1,500)]), + [] = erts_internal:maps_to_list(M,0), + [{_,_}] = erts_internal:maps_to_list(M,1), + [{_,_},{_,_}] = erts_internal:maps_to_list(M,2), + Ls1 = erts_internal:maps_to_list(M,10), + 10 = length(Ls1), + Ls2 = erts_internal:maps_to_list(M,20), + 20 = length(Ls2), + Ls3 = erts_internal:maps_to_list(M,120), + 120 = length(Ls3), + Ls4 = erts_internal:maps_to_list(M,-1), + 500 = length(Ls4), + %% error cases + {'EXIT', {{badmap,[{a,b},b]},_}} = (catch erts_internal:maps_to_list(id([{a,b},b]),id(1))), + {'EXIT', {badarg,_}} = (catch erts_internal:maps_to_list(id(#{}),id(a))), + {'EXIT', {badarg,_}} = (catch erts_internal:maps_to_list(id(#{1=>2}),id(<<>>))), + ok. + +t_bif_build_and_check(Config) when is_list(Config) -> + ok = check_build_and_remove(750,[fun(K) -> [K,K] end, + fun(K) -> [float(K),K] end, + fun(K) -> K end, + fun(K) -> {1,K} end, + fun(K) -> {K} end, + fun(K) -> [K|K] end, + fun(K) -> [K,1,2,3,4] end, + fun(K) -> {K,atom} end, + fun(K) -> float(K) end, + fun(K) -> integer_to_list(K) end, + fun(K) -> list_to_atom(integer_to_list(K)) end, + fun(K) -> [K,{K,[K,{K,[K]}]}] end, + fun(K) -> <> end]), ok. check_build_and_remove(_,[]) -> ok; -- cgit v1.2.3 From 26c3cd82529836cb5b6eefbf7f92f318fd91f847 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Fri, 10 Mar 2017 15:00:46 +0100 Subject: Update copyright year --- erts/emulator/test/Makefile | 2 +- erts/emulator/test/guard_SUITE.erl | 2 +- erts/emulator/test/num_bif_SUITE.erl | 2 +- erts/emulator/test/process_SUITE.erl | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index 453f819d1b..b8e907f769 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2016. All Rights Reserved. +# Copyright Ericsson AB 1997-2017. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/guard_SUITE.erl b/erts/emulator/test/guard_SUITE.erl index 54ee710363..1a93a9f5c2 100644 --- a/erts/emulator/test/guard_SUITE.erl +++ b/erts/emulator/test/guard_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/num_bif_SUITE.erl b/erts/emulator/test/num_bif_SUITE.erl index bb85738454..f31e73c85b 100644 --- a/erts/emulator/test/num_bif_SUITE.erl +++ b/erts/emulator/test/num_bif_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index 0a6eb7ffac..ab1587a90c 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. -- cgit v1.2.3 From 5d95b5ce9eb08f2087443c1be8de8044552daecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Mon, 13 Mar 2017 16:21:38 +0100 Subject: erts: Fix os_signal_SUITE test --- erts/emulator/test/os_signal_SUITE.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/os_signal_SUITE.erl b/erts/emulator/test/os_signal_SUITE.erl index 9aa49a453e..6bafb0e18c 100644 --- a/erts/emulator/test/os_signal_SUITE.erl +++ b/erts/emulator/test/os_signal_SUITE.erl @@ -323,7 +323,10 @@ kill(Signal, Pid) -> load_nif(Config) -> Path = proplists:get_value(data_dir, Config), - ok = erlang:load_nif(filename:join(Path,"os_signal_nif"), 0). + case erlang:load_nif(filename:join(Path,"os_signal_nif"), 0) of + ok -> ok; + {error,{reload,_}} -> ok + end. run(Program0, Args) -> run(".", Program0, Args). run(Cwd, Program0, Args) when is_list(Cwd) -> -- cgit v1.2.3 From b4b8529371f4c157ab741f30a8aeeccf16c102bc Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 14 Mar 2017 12:07:23 +0100 Subject: erts: Remove fun_r13_SUITE --- erts/emulator/test/Makefile | 1 - erts/emulator/test/fun_r13_SUITE.erl | 74 ------------------------------------ 2 files changed, 75 deletions(-) delete mode 100644 erts/emulator/test/fun_r13_SUITE.erl (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index 5478932b13..927a9366b9 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -66,7 +66,6 @@ MODULES= \ exception_SUITE \ float_SUITE \ fun_SUITE \ - fun_r13_SUITE \ gc_SUITE \ guard_SUITE \ hash_SUITE \ diff --git a/erts/emulator/test/fun_r13_SUITE.erl b/erts/emulator/test/fun_r13_SUITE.erl deleted file mode 100644 index a45ed08b9d..0000000000 --- a/erts/emulator/test/fun_r13_SUITE.erl +++ /dev/null @@ -1,74 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2007-2016. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - --module(fun_r13_SUITE). --compile(r13). - --export([all/0, suite/0, - dist_old_release/1]). - --include_lib("common_test/include/ct.hrl"). - -suite() -> - [{ct_hooks,[ts_install_cth]}, - {timetrap, {minutes, 1}}]. - -all() -> - [dist_old_release]. - -dist_old_release(Config) when is_list(Config) -> - case test_server:is_release_available("r12b") of - true -> do_dist_old(Config); - false -> {skip,"No R12B found"} - end. - -do_dist_old(Config) when is_list(Config) -> - Pa = filename:dirname(code:which(?MODULE)), - Name = fun_dist_r12, - {ok,Node} = test_server:start_node(Name, peer, - [{args,"-pa "++Pa}, - {erl,[{release,"r12b"}]}]), - - Pid = spawn_link(Node, - fun() -> - receive - Fun when is_function(Fun) -> - R12BFun = fun(H) -> cons(H, [b,c]) end, - Fun(Fun, R12BFun) - end - end), - Self = self(), - Fun = fun(F, R12BFun) -> - {pid,Self} = erlang:fun_info(F, pid), - {module,?MODULE} = erlang:fun_info(F, module), - Self ! {ok,F,R12BFun} - end, - Pid ! Fun, - receive - {ok,Fun,R12BFun} -> - [a,b,c] = R12BFun(a); - Other -> - ct:fail({bad_message,Other}) - end, - true = test_server:stop_node(Node), - ok. - -cons(H, T) -> - [H|T]. -- cgit v1.2.3 From a6ccff7ba9659cfac6d94f49b2aa39faf13e7e7d Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Fri, 17 Mar 2017 17:59:03 +0100 Subject: Fix scheduler_SUITE:update_cpu_info test-case --- erts/emulator/test/scheduler_SUITE.erl | 78 +++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 16 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl index b178dede5b..885298ce34 100644 --- a/erts/emulator/test/scheduler_SUITE.erl +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -807,21 +807,31 @@ update_cpu_info(Config) when is_list(Config) -> %% Nothing much to test; just a smoke test ok; Onln0 -> - %% unset least significant bit - Aff = (OldAff band (OldAff - 1)), - set_affinity_mask(Aff), - Onln1 = Avail - 1, - case adjust_schedulers_online() of - {Onln0, Onln1} -> - Onln1 = erlang:system_info(schedulers_online), - receive after 500 -> ok end, - io:format("TEST - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n", - [Aff, Onln1, erlang:system_info(scheduler_bindings)]), - unchanged = adjust_schedulers_online(), - ok; - Fail -> - ct:fail(Fail) - end + Cpus = bits_in_mask(OldAff), + RmCpus = case Cpus > Onln0 of + true -> Cpus - Onln0 + 1; + false -> Onln0 - Cpus + 1 + end, + Onln1 = Cpus - RmCpus, + case Onln1 > 0 of + false -> + %% Nothing much to test; just a smoke test + ok; + true -> + Aff = restrict_affinity_mask(OldAff, RmCpus), + set_affinity_mask(Aff), + case adjust_schedulers_online() of + {Onln0, Onln1} -> + Onln1 = erlang:system_info(schedulers_online), + receive after 500 -> ok end, + io:format("TEST - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n", + [Aff, Onln1, erlang:system_info(scheduler_bindings)]), + unchanged = adjust_schedulers_online(), + ok; + Fail -> + ct:fail(Fail) + end + end end after set_affinity_mask(OldAff), @@ -835,13 +845,49 @@ update_cpu_info(Config) when is_list(Config) -> end end. +bits_in_mask(Mask) -> + bits_in_mask(Mask, 0, 0). + +bits_in_mask(0, Shift, N) -> + N; +bits_in_mask(Mask, Shift, N) -> + case Mask band (1 bsl Shift) of + 0 -> bits_in_mask(Mask, Shift+1, N); + _ -> bits_in_mask(Mask band (bnot (1 bsl Shift)), + Shift+1, N+1) + end. + +restrict_affinity_mask(Mask, N) -> + try + restrict_affinity_mask(Mask, 0, N) + catch + throw : Reason -> + exit({Reason, Mask, N}) + end. + +restrict_affinity_mask(Mask, _Shift, 0) -> + Mask; +restrict_affinity_mask(0, _Shift, _N) -> + throw(overresticted_affinity_mask); +restrict_affinity_mask(Mask, Shift, N) -> + case Mask band (1 bsl Shift) of + 0 -> restrict_affinity_mask(Mask, Shift+1, N); + _ -> restrict_affinity_mask(Mask band (bnot (1 bsl Shift)), + Shift+1, N-1) + end. + adjust_schedulers_online() -> case erlang:system_info(update_cpu_info) of unchanged -> unchanged; changed -> Avail = erlang:system_info(logical_processors_available), - {erlang:system_flag(schedulers_online, Avail), Avail} + Scheds = erlang:system_info(schedulers), + SOnln = case Avail > Scheds of + true -> Scheds; + false -> Avail + end, + {erlang:system_flag(schedulers_online, SOnln), SOnln} end. read_affinity(Data) -> -- cgit v1.2.3 From 5f4324e9d9a3bd99cd06f622cb3c9c50783764ac Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Fri, 24 Mar 2017 11:42:18 +0100 Subject: Add node_container_SUITE spec --- erts/emulator/test/Makefile | 3 ++- erts/emulator/test/emulator_node_container_SUITE.spec | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 erts/emulator/test/emulator_node_container_SUITE.spec (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index 5478932b13..186f9fef8d 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -157,7 +157,8 @@ EMAKEFILE=Emakefile TEST_SPEC_FILES= emulator.spec \ emulator.spec.win \ emulator_bench.spec \ - emulator_smoke.spec + emulator_smoke.spec \ + emulator_node_container_SUITE.spec # ---------------------------------------------------- # Release directory specification diff --git a/erts/emulator/test/emulator_node_container_SUITE.spec b/erts/emulator/test/emulator_node_container_SUITE.spec new file mode 100644 index 0000000000..77c28ba7ae --- /dev/null +++ b/erts/emulator/test/emulator_node_container_SUITE.spec @@ -0,0 +1,2 @@ +{enable_builtin_hooks, false}. +{suites,"../emulator_test",node_container_SUITE}. -- cgit v1.2.3 From 8f452530e61b299d4d48f82f41ab5364723607ae Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Wed, 5 Apr 2017 14:32:16 +0200 Subject: Stack guard for PCRE --- erts/emulator/test/erts_debug_SUITE.erl | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/erts_debug_SUITE.erl b/erts/emulator/test/erts_debug_SUITE.erl index 23871585f7..c9c664de38 100644 --- a/erts/emulator/test/erts_debug_SUITE.erl +++ b/erts/emulator/test/erts_debug_SUITE.erl @@ -23,14 +23,15 @@ -export([all/0, suite/0, test_size/1,flat_size_big/1,df/1,term_type/1, - instructions/1]). + instructions/1, stack_check/1]). suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap, {minutes, 2}}]. all() -> - [test_size, flat_size_big, df, instructions, term_type]. + [test_size, flat_size_big, df, instructions, term_type, + stack_check]. test_size(Config) when is_list(Config) -> ConsCell1 = id([a|b]), @@ -181,6 +182,15 @@ df(Config) when is_list(Config) -> true = (P0 == pps()), ok. +stack_check(Config) when is_list(Config) -> + erts_debug:set_internal_state(available_internal_state,true), + %% Recurses on the C stack until stacklimit is reached. That + %% is, tests that the stack limit functionality works (used + %% by PCRE). VM will crash if it doesn't work... + Size = erts_debug:get_internal_state(stack_check), + erts_debug:set_internal_state(available_internal_state,false), + {comment, "Stack size: "++integer_to_list(Size)++" bytes"}. + df_smoke([M|Ms]) -> io:format("~p", [M]), erts_debug:df(M), -- cgit v1.2.3 From 0835f40ae25f97360dc393928796387d3cd6b16e Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Wed, 19 Apr 2017 00:43:37 +0100 Subject: erts: Add enif_phash2 and enif_phash2_ranged These allow one to hash VM terms from NIF code. --- erts/emulator/test/nif_SUITE.erl | 85 ++++++++++++++++++++++++++- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 19 ++++++ 2 files changed, 102 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 693db42e58..780fe0a5ee 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -56,7 +56,9 @@ nif_is_process_alive/1, nif_is_port_alive/1, nif_term_to_binary/1, nif_binary_to_term/1, nif_port_command/1, - nif_snprintf/1 + nif_snprintf/1, + nif_phash2/1, + nif_phash2_ranged/1 ]). -export([many_args_100/100]). @@ -90,7 +92,9 @@ all() -> nif_is_process_alive, nif_is_port_alive, nif_term_to_binary, nif_binary_to_term, nif_port_command, - nif_snprintf]. + nif_snprintf, + nif_phash2, + nif_phash2_ranged]. groups() -> [{G, [], api_repeaters()} || G <- api_groups()] @@ -2610,6 +2614,81 @@ nif_snprintf(Config) -> <<"{{hello,world,-33},",0>> = format_term_nif(20,{{hello,world, -33}, 3.14, self()}), ok. +nif_phash2(Config) -> + ensure_lib_loaded(Config), + Terms = + [random_term() || _ <- lists:seq(1, 1000)], + + lists:foreach( + fun (Term) -> + HashValue = erlang:phash2(Term), + NifHashValue = phash2_nif(Term), + (HashValue =:= NifHashValue + orelse ct:fail("Expected: ~p\nActual: ~p", + [HashValue, NifHashValue])) + end, + Terms). + +nif_phash2_ranged(Config) -> + ensure_lib_loaded(Config), + RandomRangedTerms = + [{random_term(), rand:uniform((1 bsl 32) - 1)} + || _ <- lists:seq(1, 1000)], + + lists:foreach( + fun ({Term, Range}) -> + HashValue = erlang:phash2(Term, Range), + NifHashValue = phash2_ranged_nif(Term, Range), + (HashValue =:= NifHashValue + orelse ct:fail("Expected: ~p\nActual: ~p", + [HashValue, NifHashValue])) + end, + RandomRangedTerms), + + EdgeCaseTerm = random_term(), + EdgeCaseHashValue = erlang:phash2(EdgeCaseTerm, 1 bsl 32), + EdgeCaseNifHashValue = phash2_ranged_nif(EdgeCaseTerm, 0), + (EdgeCaseHashValue =:= EdgeCaseNifHashValue + orelse ct:fail("Expected: ~p\nActual: ~p", + [EdgeCaseHashValue, EdgeCaseNifHashValue])). + +-define(HALF_DBL_EPSILON, 1.1102230246251565e-16). % math:pow(2, -53) + +random_term() -> + case rand:uniform(6) of + 1 -> rand:uniform(1 bsl 27) - 1; % small + 2 -> (1 bsl 27) + rand:uniform(1 bsl 128); % big + 3 -> random_sign() * (rand:uniform() * ?HALF_DBL_EPSILON); % float + 4 -> random_binary(); + 5 -> random_pid(); + 6 -> + Length = rand:uniform(10), + List = [random_term() || _ <- lists:seq(1, Length)], + case rand:uniform(2) of + 1 -> + List; + 2 -> + list_to_tuple(List) + end + end. + +random_sign() -> + case rand:uniform(2) of + 1 -> -1.0; + 2 -> 1.0 + end. + +random_binary() -> + list_to_binary(random_bytes(rand:uniform(32) - 1)). + +random_bytes(0) -> + []; +random_bytes(N) when N > 0 -> + [rand:uniform(256) - 1 | random_bytes(N - 1)]. + +random_pid() -> + Processes = erlang:processes(), + lists:nth(rand:uniform(length(Processes)), Processes). %% The NIFs: lib_version() -> undefined. @@ -2621,6 +2700,8 @@ type_test() -> ?nif_stub. tuple_2_list(_) -> ?nif_stub. is_identical(_,_) -> ?nif_stub. compare(_,_) -> ?nif_stub. +phash2_nif(_) -> ?nif_stub. +phash2_ranged_nif(_, _) -> ?nif_stub. many_args_100(_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_) -> ?nif_stub. clone_bin(_) -> ?nif_stub. make_sub_bin(_,_,_) -> ?nif_stub. diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 8fe5ee809a..3bdd4d93c7 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -687,6 +687,23 @@ static ERL_NIF_TERM compare(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) return enif_make_int(env, enif_compare(argv[0],argv[1])); } +static ERL_NIF_TERM phash2_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + if (argc != 1) { + return enif_make_badarg(env); + } + return enif_make_ulong(env, enif_phash2(argv[0])); +} + +static ERL_NIF_TERM phash2_ranged_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + unsigned long range; + if (argc != 2 || !enif_get_ulong(env, argv[1], &range)) { + return enif_make_badarg(env); + } + return enif_make_ulong(env, enif_phash2_ranged(argv[0], range)); +} + static ERL_NIF_TERM many_args_100(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { int i, k; @@ -2864,6 +2881,8 @@ static ErlNifFunc nif_funcs[] = {"tuple_2_list", 1, tuple_2_list}, {"is_identical",2,is_identical}, {"compare",2,compare}, + {"phash2_nif",1,phash2_nif}, + {"phash2_ranged_nif",2,phash2_ranged_nif}, {"many_args_100", 100, many_args_100}, {"clone_bin", 1, clone_bin}, {"make_sub_bin", 3, make_sub_bin}, -- cgit v1.2.3 From 0326b22639d0c8c5f915aed34ad3e099e4ee4642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 19 Apr 2017 12:46:44 +0200 Subject: Do atom roundtripping with an R16B node It is no longer possible to communicate with R15B nodes. --- erts/emulator/test/distribution_SUITE.erl | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl index 6994bfef83..4f98cd6cee 100644 --- a/erts/emulator/test/distribution_SUITE.erl +++ b/erts/emulator/test/distribution_SUITE.erl @@ -19,7 +19,7 @@ %% -module(distribution_SUITE). --compile(r15). +-compile(r16). -define(VERSION_MAGIC, 131). @@ -48,7 +48,7 @@ dist_parallel_send/1, atom_roundtrip/1, unicode_atom_roundtrip/1, - atom_roundtrip_r15b/1, + atom_roundtrip_r16b/1, contended_atom_cache_entry/1, contended_unicode_atom_cache_entry/1, bad_dist_structure/1, @@ -78,7 +78,8 @@ all() -> link_to_dead_new_node, applied_monitor_node, ref_port_roundtrip, nil_roundtrip, stop_dist, {group, trap_bif}, {group, dist_auto_connect}, - dist_parallel_send, atom_roundtrip, unicode_atom_roundtrip, atom_roundtrip_r15b, + dist_parallel_send, atom_roundtrip, unicode_atom_roundtrip, + atom_roundtrip_r16b, contended_atom_cache_entry, contended_unicode_atom_cache_entry, bad_dist_structure, {group, bad_dist_ext}, start_epmd_false, epmd_module]. @@ -1032,21 +1033,21 @@ atom_roundtrip(Config) when is_list(Config) -> stop_node(Node), ok. -atom_roundtrip_r15b(Config) when is_list(Config) -> - case test_server:is_release_available("r15b") of +atom_roundtrip_r16b(Config) when is_list(Config) -> + case test_server:is_release_available("r16b") of true -> ct:timetrap({minutes, 6}), - AtomData = atom_data(), + AtomData = unicode_atom_data(), verify_atom_data(AtomData), - case start_node(Config, [], "r15b") of + case start_node(Config, [], "r16b") of {ok, Node} -> do_atom_roundtrip(Node, AtomData), stop_node(Node); {error, timeout} -> - {skip,"Unable to start OTP R15B release"} + {skip,"Unable to start OTP R16B release"} end; false -> - {skip,"No OTP R15B available"} + {skip,"No OTP R16B available"} end. unicode_atom_roundtrip(Config) when is_list(Config) -> -- cgit v1.2.3 From 8121b6af55ba485fe58a9dbfb0f1180393b86a3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 19 Apr 2017 12:54:56 +0200 Subject: Remove test case for testing compatibility with R9B It is no longer possible to commuicate with R9B nodes. --- erts/emulator/test/Makefile | 1 - erts/emulator/test/node_container_SUITE.erl | 32 +------------------ erts/emulator/test/old_mod.erl | 48 ----------------------------- 3 files changed, 1 insertion(+), 80 deletions(-) delete mode 100644 erts/emulator/test/old_mod.erl (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index 8c8c73aa3e..ca81c9915e 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -121,7 +121,6 @@ MODULES= \ port_trace_SUITE \ unique_SUITE \ z_SUITE \ - old_mod \ long_timers_test \ ignore_cores \ dgawd_handler \ diff --git a/erts/emulator/test/node_container_SUITE.erl b/erts/emulator/test/node_container_SUITE.erl index 291d3ee30d..30518a5b27 100644 --- a/erts/emulator/test/node_container_SUITE.erl +++ b/erts/emulator/test/node_container_SUITE.erl @@ -45,7 +45,6 @@ ets_refc/1, match_spec_refc/1, timer_refc/1, - otp_4715/1, pid_wrap/1, port_wrap/1, bad_nc/1, @@ -62,7 +61,7 @@ all() -> [term_to_binary_to_term_eq, round_trip_eq, cmp, ref_eq, node_table_gc, dist_link_refc, dist_monitor_refc, node_controller_refc, ets_refc, match_spec_refc, - timer_refc, otp_4715, pid_wrap, port_wrap, bad_nc, + timer_refc, pid_wrap, port_wrap, bad_nc, unique_pid, iter_max_procs, magic_ref]. init_per_suite(Config) -> @@ -684,35 +683,6 @@ timer_refc(Config) when is_list(Config) -> nc_refc_check(node()), ok. -otp_4715(Config) when is_list(Config) -> - case test_server:is_release_available("r9b") of - true -> otp_4715_1(Config); - false -> {skip,"No R9B found"} - end. - -otp_4715_1(Config) -> - case erlang:system_info(compat_rel) of - 9 -> - run_otp_4715(Config); - _ -> - Pa = filename:dirname(code:which(?MODULE)), - test_server:run_on_shielded_node(fun () -> - run_otp_4715(Config) - end, - "+R9 -pa " ++ Pa) - end. - -run_otp_4715(Config) when is_list(Config) -> - erts_debug:set_internal_state(available_internal_state, true), - PidList = [mk_pid({a@b, 1}, 4710, 2), - mk_pid({a@b, 1}, 4712, 1), - mk_pid({c@b, 1}, 4711, 1), - mk_pid({b@b, 3}, 4711, 1), - mk_pid({b@b, 2}, 4711, 1)], - - R9Sorted = old_mod:sort_on_old_node(PidList), - R9Sorted = lists:sort(PidList). - pid_wrap(Config) when is_list(Config) -> pp_wrap(pid). port_wrap(Config) when is_list(Config) -> diff --git a/erts/emulator/test/old_mod.erl b/erts/emulator/test/old_mod.erl deleted file mode 100644 index 866aba79bb..0000000000 --- a/erts/emulator/test/old_mod.erl +++ /dev/null @@ -1,48 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2003-2016. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - --module(old_mod). --compile(r10). - --export([sort_on_old_node/1, sorter/3]). - --include_lib("common_test/include/ct.hrl"). - -sorter(Receiver, Ref, List) -> - Receiver ! {Ref, lists:sort(List)}. - -sort_on_old_node(List) when is_list(List) -> - OldVersion = "r10", - Pa = filename:dirname(code:which(?MODULE)), - {X, Y, Z} = now(), - NodeName = list_to_atom(OldVersion - ++ "_" - ++ integer_to_list(X) - ++ integer_to_list(Y) - ++ integer_to_list(Z)), - {ok, Node} = test_server:start_node(NodeName, - peer, - [{args, " -pa " ++ Pa}, - {erl, [{release, OldVersion++"b_patched"}]}]), - Ref = make_ref(), - spawn_link(Node, ?MODULE, sorter, [self(), Ref, List]), - SortedPids = receive {Ref, SP} -> SP end, - true = test_server:stop_node(Node), - SortedPids. -- cgit v1.2.3 From 1b37d0b010ea31b04b9d0a15d0bec9c75a013dc9 Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Thu, 20 Apr 2017 21:35:54 +0100 Subject: erts: Remove enif_phash2_ranged --- erts/emulator/test/nif_SUITE.erl | 30 ++------------------------- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 10 --------- 2 files changed, 2 insertions(+), 38 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 780fe0a5ee..f868b018c9 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -57,8 +57,7 @@ nif_term_to_binary/1, nif_binary_to_term/1, nif_port_command/1, nif_snprintf/1, - nif_phash2/1, - nif_phash2_ranged/1 + nif_phash2/1 ]). -export([many_args_100/100]). @@ -93,8 +92,7 @@ all() -> nif_term_to_binary, nif_binary_to_term, nif_port_command, nif_snprintf, - nif_phash2, - nif_phash2_ranged]. + nif_phash2]. groups() -> [{G, [], api_repeaters()} || G <- api_groups()] @@ -2629,29 +2627,6 @@ nif_phash2(Config) -> end, Terms). -nif_phash2_ranged(Config) -> - ensure_lib_loaded(Config), - RandomRangedTerms = - [{random_term(), rand:uniform((1 bsl 32) - 1)} - || _ <- lists:seq(1, 1000)], - - lists:foreach( - fun ({Term, Range}) -> - HashValue = erlang:phash2(Term, Range), - NifHashValue = phash2_ranged_nif(Term, Range), - (HashValue =:= NifHashValue - orelse ct:fail("Expected: ~p\nActual: ~p", - [HashValue, NifHashValue])) - end, - RandomRangedTerms), - - EdgeCaseTerm = random_term(), - EdgeCaseHashValue = erlang:phash2(EdgeCaseTerm, 1 bsl 32), - EdgeCaseNifHashValue = phash2_ranged_nif(EdgeCaseTerm, 0), - (EdgeCaseHashValue =:= EdgeCaseNifHashValue - orelse ct:fail("Expected: ~p\nActual: ~p", - [EdgeCaseHashValue, EdgeCaseNifHashValue])). - -define(HALF_DBL_EPSILON, 1.1102230246251565e-16). % math:pow(2, -53) random_term() -> @@ -2701,7 +2676,6 @@ tuple_2_list(_) -> ?nif_stub. is_identical(_,_) -> ?nif_stub. compare(_,_) -> ?nif_stub. phash2_nif(_) -> ?nif_stub. -phash2_ranged_nif(_, _) -> ?nif_stub. many_args_100(_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_) -> ?nif_stub. clone_bin(_) -> ?nif_stub. make_sub_bin(_,_,_) -> ?nif_stub. diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 3bdd4d93c7..dac6d02e9d 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -695,15 +695,6 @@ static ERL_NIF_TERM phash2_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv return enif_make_ulong(env, enif_phash2(argv[0])); } -static ERL_NIF_TERM phash2_ranged_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ - unsigned long range; - if (argc != 2 || !enif_get_ulong(env, argv[1], &range)) { - return enif_make_badarg(env); - } - return enif_make_ulong(env, enif_phash2_ranged(argv[0], range)); -} - static ERL_NIF_TERM many_args_100(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { int i, k; @@ -2882,7 +2873,6 @@ static ErlNifFunc nif_funcs[] = {"is_identical",2,is_identical}, {"compare",2,compare}, {"phash2_nif",1,phash2_nif}, - {"phash2_ranged_nif",2,phash2_ranged_nif}, {"many_args_100", 100, many_args_100}, {"clone_bin", 1, clone_bin}, {"make_sub_bin", 3, make_sub_bin}, -- cgit v1.2.3 From 5ad95cca3f3c6802cd71fdd35dd397c3a37dc239 Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Thu, 20 Apr 2017 21:53:54 +0100 Subject: erts: Fix random floats in enif_phash2 tests --- erts/emulator/test/nif_SUITE.erl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index f868b018c9..9127a5eae9 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -2627,13 +2627,11 @@ nif_phash2(Config) -> end, Terms). --define(HALF_DBL_EPSILON, 1.1102230246251565e-16). % math:pow(2, -53) - random_term() -> case rand:uniform(6) of 1 -> rand:uniform(1 bsl 27) - 1; % small 2 -> (1 bsl 27) + rand:uniform(1 bsl 128); % big - 3 -> random_sign() * (rand:uniform() * ?HALF_DBL_EPSILON); % float + 3 -> random_sign() * (rand:uniform() * (1 bsl 53)); % float 4 -> random_binary(); 5 -> random_pid(); 6 -> -- cgit v1.2.3 From d8756f8665a42effa2f3515369058cff4441abeb Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Thu, 20 Apr 2017 22:44:04 +0100 Subject: erts: Refactor enif_phash2 into enif_hash A more generic hashing function which can also hash terms based on `make_internal_hash'. --- erts/emulator/test/nif_SUITE.erl | 47 +++++++++++++++++++++++++-- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 20 +++++++++--- 2 files changed, 60 insertions(+), 7 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 9127a5eae9..e177fa4963 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -57,6 +57,7 @@ nif_term_to_binary/1, nif_binary_to_term/1, nif_port_command/1, nif_snprintf/1, + nif_internal_hash/1, nif_phash2/1 ]). @@ -92,6 +93,7 @@ all() -> nif_term_to_binary, nif_binary_to_term, nif_port_command, nif_snprintf, + nif_internal_hash, nif_phash2]. groups() -> @@ -2612,15 +2614,54 @@ nif_snprintf(Config) -> <<"{{hello,world,-33},",0>> = format_term_nif(20,{{hello,world, -33}, 3.14, self()}), ok. +nif_internal_hash(Config) -> + ensure_lib_loaded(Config), + Terms = + [random_term() || _ <- lists:seq(1, 5000)], + + % Unlike the phash2 hash, in this case we + % have nothing to compare to, so let's try + % and at least make sure the distribution + % isn't outright wrong, statistical nuances + % aside. + + OnesPerBit = + lists:foldl( + fun (Term, Acc) -> + NifHashValue = hash_nif(internal, Term), + lists:foldl( + fun (BitIndex, AccB) -> + BitValue = (NifHashValue band (1 bsl BitIndex)) bsr BitIndex, + dict:update_counter(BitIndex, BitValue, AccB) + end, + Acc, + lists:seq(0, 31)) + end, + dict:new(), + Terms), + + ExpectedNrOfOnes = length(Terms) div 2, + dict:fold( + fun (BitIndex, NrOfOnes, Acc) -> + RelativeDeviation = abs(NrOfOnes - ExpectedNrOfOnes) / ExpectedNrOfOnes, + (RelativeDeviation < 0.10 + orelse ct:fail("Unreasonable deviation on number of set bits (i=~p): " + "expected ~p, got ~p (relative dev. ~.3f)", + [BitIndex, ExpectedNrOfOnes, NrOfOnes, RelativeDeviation])), + Acc + end, + ok, + OnesPerBit). + nif_phash2(Config) -> ensure_lib_loaded(Config), Terms = - [random_term() || _ <- lists:seq(1, 1000)], + [random_term() || _ <- lists:seq(1, 5000)], lists:foreach( fun (Term) -> HashValue = erlang:phash2(Term), - NifHashValue = phash2_nif(Term), + NifHashValue = hash_nif(phash2, Term), (HashValue =:= NifHashValue orelse ct:fail("Expected: ~p\nActual: ~p", [HashValue, NifHashValue])) @@ -2673,7 +2714,7 @@ type_test() -> ?nif_stub. tuple_2_list(_) -> ?nif_stub. is_identical(_,_) -> ?nif_stub. compare(_,_) -> ?nif_stub. -phash2_nif(_) -> ?nif_stub. +hash_nif(_, _) -> ?nif_stub. many_args_100(_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_) -> ?nif_stub. clone_bin(_) -> ?nif_stub. make_sub_bin(_,_,_) -> ?nif_stub. diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index dac6d02e9d..9d65b9c09b 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -687,12 +687,24 @@ static ERL_NIF_TERM compare(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) return enif_make_int(env, enif_compare(argv[0],argv[1])); } -static ERL_NIF_TERM phash2_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - if (argc != 1) { + if (argc != 2) { + return enif_make_badarg(env); + } + + ErlNifHash type; + if (enif_is_identical(argv[0], enif_make_atom(env, "internal"))) { + type = ERL_NIF_INTERNAL_HASH; + } + else if (enif_is_identical(argv[0], enif_make_atom(env, "phash2"))) { + type = ERL_NIF_PHASH2; + } + else { return enif_make_badarg(env); } - return enif_make_ulong(env, enif_phash2(argv[0])); + + return enif_make_ulong(env, enif_hash(type, argv[1])); } static ERL_NIF_TERM many_args_100(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) @@ -2872,7 +2884,7 @@ static ErlNifFunc nif_funcs[] = {"tuple_2_list", 1, tuple_2_list}, {"is_identical",2,is_identical}, {"compare",2,compare}, - {"phash2_nif",1,phash2_nif}, + {"hash_nif",2,hash_nif}, {"many_args_100", 100, many_args_100}, {"clone_bin", 1, clone_bin}, {"make_sub_bin", 3, make_sub_bin}, -- cgit v1.2.3 From f30d131bd979e29b68fb7d9ff515c61a246201f4 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 21 Mar 2017 13:40:08 +0100 Subject: erts: Deprecate the non-smp emulators --- erts/emulator/test/smoke_test_SUITE.erl | 7 ------- 1 file changed, 7 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/smoke_test_SUITE.erl b/erts/emulator/test/smoke_test_SUITE.erl index 5eccdc562b..45b28b28a5 100644 --- a/erts/emulator/test/smoke_test_SUITE.erl +++ b/erts/emulator/test/smoke_test_SUITE.erl @@ -66,17 +66,10 @@ boot_combo(Config) when is_list(Config) -> ok end end, - SMPDisable = fun () -> false = erlang:system_info(smp_support) end, try chk_boot(Config, "+Ktrue", NOOP), chk_boot(Config, "+A42", A42), - chk_boot(Config, "-smp disable", SMPDisable), chk_boot(Config, "+Ktrue +A42", A42), - chk_boot(Config, "-smp disable +A42", - fun () -> SMPDisable(), A42() end), - chk_boot(Config, "-smp disable +Ktrue", SMPDisable), - chk_boot(Config, "-smp disable +Ktrue +A42", - fun () -> SMPDisable(), A42() end), %% A lot more combos could be implemented... ok after -- cgit v1.2.3 From 8434b76e48b4ad1fe47b1d38dc3cac0b50d7d52d Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 10 Apr 2017 09:41:46 +0200 Subject: erts: Fix testcases for smp +S 1:1 --- erts/emulator/test/scheduler_SUITE.erl | 16 ++++------------ erts/emulator/test/statistics_SUITE.erl | 4 ++-- 2 files changed, 6 insertions(+), 14 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl index 885298ce34..64e51e7d7c 100644 --- a/erts/emulator/test/scheduler_SUITE.erl +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -1087,12 +1087,8 @@ scheduler_threads(Config) when is_list(Config) -> {Sched, SchedOnln, _} = get_sstate(Config, ""), %% Configure half the number of both the scheduler threads and %% the scheduler threads online. - {HalfSched, HalfSchedOnln} = case SmpSupport of - false -> {1,1}; - true -> - {Sched div 2, - SchedOnln div 2} - end, + {HalfSched, HalfSchedOnln} = {lists:max([1,Sched div 2]), + lists:max([1,SchedOnln div 2])}, {HalfSched, HalfSchedOnln, _} = get_sstate(Config, "+SP 50:50"), %% Use +S to configure 4x the number of scheduler threads and %% 4x the number of scheduler threads online, but alter that @@ -1149,12 +1145,8 @@ dirty_scheduler_threads(Config) when is_list(Config) -> dirty_scheduler_threads_test(Config) -> SmpSupport = erlang:system_info(smp_support), {Sched, SchedOnln, _} = get_dsstate(Config, ""), - {HalfSched, HalfSchedOnln} = case SmpSupport of - false -> {1,1}; - true -> - {Sched div 2, - SchedOnln div 2} - end, + {HalfSched, HalfSchedOnln} = {lists:max([1,Sched div 2]), + lists:max([1,SchedOnln div 2])}, Cmd1 = "+SDcpu "++integer_to_list(HalfSched)++":"++ integer_to_list(HalfSchedOnln), {HalfSched, HalfSchedOnln, _} = get_dsstate(Config, Cmd1), diff --git a/erts/emulator/test/statistics_SUITE.erl b/erts/emulator/test/statistics_SUITE.erl index f51244485b..729e86cb4f 100644 --- a/erts/emulator/test/statistics_SUITE.erl +++ b/erts/emulator/test/statistics_SUITE.erl @@ -329,9 +329,9 @@ scheduler_wall_time_test(Type) -> %% 50% load HalfHogs = [StartHog() || _ <- lists:seq(1, (Schedulers-1) div 2)], HalfDirtyCPUHogs = [StartDirtyHog(dirty_cpu) - || _ <- lists:seq(1, DirtyCPUSchedulers div 2)], + || _ <- lists:seq(1, lists:max([1,DirtyCPUSchedulers div 2]))], HalfDirtyIOHogs = [StartDirtyHog(dirty_io) - || _ <- lists:seq(1, DirtyIOSchedulers div 2)], + || _ <- lists:seq(1, lists:max([1,DirtyIOSchedulers div 2]))], HalfLoad = lists:sum(get_load(Type)) div TotLoadSchedulers, if Schedulers < 2, HalfLoad > 80 -> ok; %% Ok only one scheduler online and one hog %% We want roughly 50% load -- cgit v1.2.3 From 21e1d879faaae2278a68200fe1085d7e73791fa0 Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Sat, 22 Apr 2017 17:22:32 +0100 Subject: erts: Support custom salt in enif_hash --- erts/emulator/test/nif_SUITE.erl | 6 +++--- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 11 ++++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index e177fa4963..36af68be60 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -2628,7 +2628,7 @@ nif_internal_hash(Config) -> OnesPerBit = lists:foldl( fun (Term, Acc) -> - NifHashValue = hash_nif(internal, Term), + NifHashValue = hash_nif(internal, Term, 0), lists:foldl( fun (BitIndex, AccB) -> BitValue = (NifHashValue band (1 bsl BitIndex)) bsr BitIndex, @@ -2661,7 +2661,7 @@ nif_phash2(Config) -> lists:foreach( fun (Term) -> HashValue = erlang:phash2(Term), - NifHashValue = hash_nif(phash2, Term), + NifHashValue = hash_nif(phash2, Term, 0), (HashValue =:= NifHashValue orelse ct:fail("Expected: ~p\nActual: ~p", [HashValue, NifHashValue])) @@ -2714,7 +2714,7 @@ type_test() -> ?nif_stub. tuple_2_list(_) -> ?nif_stub. is_identical(_,_) -> ?nif_stub. compare(_,_) -> ?nif_stub. -hash_nif(_, _) -> ?nif_stub. +hash_nif(_Type, _Term, _Salt) -> ?nif_stub. many_args_100(_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_) -> ?nif_stub. clone_bin(_) -> ?nif_stub. make_sub_bin(_,_,_) -> ?nif_stub. diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 9d65b9c09b..2a80d48b62 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -689,7 +689,7 @@ static ERL_NIF_TERM compare(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - if (argc != 2) { + if (argc != 3) { return enif_make_badarg(env); } @@ -704,7 +704,12 @@ static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] return enif_make_badarg(env); } - return enif_make_ulong(env, enif_hash(type, argv[1])); + unsigned long salt; + if (! enif_get_ulong(env, argv[2], &salt)) { + return enif_make_badarg(env); + } + + return enif_make_ulong(env, enif_hash(type, argv[1], salt)); } static ERL_NIF_TERM many_args_100(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) @@ -2884,7 +2889,7 @@ static ErlNifFunc nif_funcs[] = {"tuple_2_list", 1, tuple_2_list}, {"is_identical",2,is_identical}, {"compare",2,compare}, - {"hash_nif",2,hash_nif}, + {"hash_nif",3,hash_nif}, {"many_args_100", 100, many_args_100}, {"clone_bin", 1, clone_bin}, {"make_sub_bin", 3, make_sub_bin}, -- cgit v1.2.3 From c94506ccc003016db49fa2dbe5741196e071d45a Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Sat, 22 Apr 2017 18:40:26 +0100 Subject: erts: Add test cases for salted enif_hash calls --- erts/emulator/test/nif_SUITE.erl | 148 ++++++++++++++++++++++++++++----------- 1 file changed, 107 insertions(+), 41 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 36af68be60..6e4866bfd8 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -58,7 +58,9 @@ nif_port_command/1, nif_snprintf/1, nif_internal_hash/1, - nif_phash2/1 + nif_internal_hash_salted/1, + nif_phash2/1, + nif_phash2_salted/1 ]). -export([many_args_100/100]). @@ -94,7 +96,9 @@ all() -> nif_port_command, nif_snprintf, nif_internal_hash, - nif_phash2]. + nif_internal_hash_salted, + nif_phash2, + nif_phash2_salted]. groups() -> [{G, [], api_repeaters()} || G <- api_groups()] @@ -2616,57 +2620,119 @@ nif_snprintf(Config) -> nif_internal_hash(Config) -> ensure_lib_loaded(Config), - Terms = - [random_term() || _ <- lists:seq(1, 5000)], + HashValueBitSize = nif_hash_result_bitsize(internal), + Terms = unique([random_term() || _ <- lists:seq(1, 5000)]), + HashValues = [hash_nif(internal, Term, 0) || Term <- Terms], + test_bit_distribution_fitness(HashValues, HashValueBitSize, 0.05). - % Unlike the phash2 hash, in this case we - % have nothing to compare to, so let's try - % and at least make sure the distribution - % isn't outright wrong, statistical nuances - % aside. +nif_internal_hash_salted(Config) -> + ensure_lib_loaded(Config), + test_salted_nif_hash(internal). + +nif_phash2(Config) -> + ensure_lib_loaded(Config), + HashValueBitSize = nif_hash_result_bitsize(phash2), + Terms = unique([random_term() || _ <- lists:seq(1, 5000)]), + HashValues = + lists:map( + fun (Term) -> + HashValue = erlang:phash2(Term), + NifHashValue = hash_nif(phash2, Term, 0), + (HashValue =:= NifHashValue + orelse ct:fail("Expected: ~p\nActual: ~p", + [HashValue, NifHashValue])), + HashValue + end, + Terms), + test_bit_distribution_fitness(HashValues, HashValueBitSize, 0.05). + +nif_phash2_salted(Config) -> + ensure_lib_loaded(Config), + test_salted_nif_hash(phash2). + +test_salted_nif_hash(HashType) -> + HashValueBitSize = nif_hash_result_bitsize(HashType), + Terms = unique([random_term() || _ <- lists:seq(1, 5000)]), + Salts = unique([random_uint32() || _ <- lists:seq(1, 100)]), + {HashValuesPerSalt, HashValuesPerTerm} = + lists:mapfoldl( + fun (Salt, Acc) -> + {HashValues, NewAcc} = + lists:mapfoldl( + fun (Term, AccB) -> + HashValue = hash_nif(HashType, Term, Salt), + NewAccB = dict:append(Term, HashValue, AccB), + {HashValue, NewAccB} + end, + Acc, + Terms), + {{Salt, HashValues}, NewAcc} + end, + dict:new(), + Salts), + + % Test per-salt hash distribution of different terms + lists:foreach( + fun ({_Salt, HashValues}) -> + test_bit_distribution_fitness(HashValues, HashValueBitSize, 0.05) + end, + HashValuesPerSalt), + % Test per-term hash distribution of different salts + dict:fold( + fun (_Term, HashValues, Acc) -> + % Be more tolerant of relative deviation, + % as there's fewer hash values here. + test_bit_distribution_fitness(HashValues, HashValueBitSize, 0.30), + Acc + end, + ok, + HashValuesPerTerm). + +test_bit_distribution_fitness(Integers, BitSize, MaxRelativeDeviation) -> + MaxInteger = (1 bsl BitSize) - 1, OnesPerBit = lists:foldl( - fun (Term, Acc) -> - NifHashValue = hash_nif(internal, Term, 0), + fun (Integer, Acc) when Integer >= 0, Integer =< MaxInteger -> lists:foldl( fun (BitIndex, AccB) -> - BitValue = (NifHashValue band (1 bsl BitIndex)) bsr BitIndex, - dict:update_counter(BitIndex, BitValue, AccB) + BitValue = (Integer band (1 bsl BitIndex)) bsr BitIndex, + orddict:update_counter(BitIndex, BitValue, AccB) end, Acc, - lists:seq(0, 31)) + lists:seq(0, BitSize - 1)) end, - dict:new(), - Terms), + orddict:new(), + Integers), + + ExpectedNrOfOnes = length(Integers) div 2, + FailureText = + orddict:fold( + fun (BitIndex, NrOfOnes, Acc) -> + RelativeDeviation = abs(NrOfOnes - ExpectedNrOfOnes) / length(Integers), + case RelativeDeviation >= MaxRelativeDeviation of + false -> Acc; + true -> + [Acc, + io_lib:format( + "Unreasonable deviation on number of set bits (i=~p): " + "expected ~p, got ~p (relative dev. ~.3f)~n", + [BitIndex, ExpectedNrOfOnes, NrOfOnes, RelativeDeviation])] + end + end, + [], + OnesPerBit), - ExpectedNrOfOnes = length(Terms) div 2, - dict:fold( - fun (BitIndex, NrOfOnes, Acc) -> - RelativeDeviation = abs(NrOfOnes - ExpectedNrOfOnes) / ExpectedNrOfOnes, - (RelativeDeviation < 0.10 - orelse ct:fail("Unreasonable deviation on number of set bits (i=~p): " - "expected ~p, got ~p (relative dev. ~.3f)", - [BitIndex, ExpectedNrOfOnes, NrOfOnes, RelativeDeviation])), - Acc - end, - ok, - OnesPerBit). + (FailureText =:= [] orelse ct:fail(FailureText)). -nif_phash2(Config) -> - ensure_lib_loaded(Config), - Terms = - [random_term() || _ <- lists:seq(1, 5000)], +nif_hash_result_bitsize(internal) -> 32; +nif_hash_result_bitsize(phash2) -> 27. - lists:foreach( - fun (Term) -> - HashValue = erlang:phash2(Term), - NifHashValue = hash_nif(phash2, Term, 0), - (HashValue =:= NifHashValue - orelse ct:fail("Expected: ~p\nActual: ~p", - [HashValue, NifHashValue])) - end, - Terms). +unique(List) -> + lists:usort(List). + +random_uint32() -> + rand:uniform(1 bsl 32) - 1. random_term() -> case rand:uniform(6) of -- cgit v1.2.3 From da9abd24a93ae8fe174cdd38fc9699bbc45fdf56 Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Sat, 22 Apr 2017 20:00:28 +0100 Subject: erts: Allow for easier future enif_hash expansion Allow for expanding support to 64-bit hashes without breaking the interface. --- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 2a80d48b62..a255c9f096 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -704,12 +704,12 @@ static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] return enif_make_badarg(env); } - unsigned long salt; - if (! enif_get_ulong(env, argv[2], &salt)) { + ErlNifUInt64 salt; + if (! enif_get_uint64(env, argv[2], &salt)) { return enif_make_badarg(env); } - return enif_make_ulong(env, enif_hash(type, argv[1], salt)); + return enif_make_uint64(env, enif_hash(type, argv[1], salt)); } static ERL_NIF_TERM many_args_100(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -- cgit v1.2.3 From a9d0d119837fb0bc52d2bb3d48a47568de9100b4 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Tue, 28 Feb 2017 15:23:11 +0100 Subject: Handle chardata in string:to_float and string:to_list --- erts/emulator/test/list_bif_SUITE.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/list_bif_SUITE.erl b/erts/emulator/test/list_bif_SUITE.erl index 514dd2f412..9c40929926 100644 --- a/erts/emulator/test/list_bif_SUITE.erl +++ b/erts/emulator/test/list_bif_SUITE.erl @@ -47,9 +47,9 @@ t_list_to_integer(Config) when is_list(Config) -> {12373281903728109372810937209817320981321,"ABC"} = string:to_integer("12373281903728109372810937209817320981321ABC"), {-12373281903728109372810937209817320981321,"ABC"} = string:to_integer("-12373281903728109372810937209817320981321ABC"), {12,[345]} = string:to_integer([$1,$2,345]), - {12,[a]} = string:to_integer([$1,$2,a]), + {error, badarg} = string:to_integer([$1,$2,a]), {error,no_integer} = string:to_integer([$A]), - {error,not_a_list} = string:to_integer($A), + {error,badarg} = string:to_integer($A), ok. %% Test hd/1 with correct and incorrect arguments. -- cgit v1.2.3 From 3d6b8e7fb68543713f1620a45b8a590ef4ed88a5 Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Mon, 24 Apr 2017 22:51:49 +0100 Subject: erts: Discontinue salted use of enif_hash/phash2 --- erts/emulator/test/nif_SUITE.erl | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 6e4866bfd8..8ad11d3bf3 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -59,8 +59,7 @@ nif_snprintf/1, nif_internal_hash/1, nif_internal_hash_salted/1, - nif_phash2/1, - nif_phash2_salted/1 + nif_phash2/1 ]). -export([many_args_100/100]). @@ -97,8 +96,7 @@ all() -> nif_snprintf, nif_internal_hash, nif_internal_hash_salted, - nif_phash2, - nif_phash2_salted]. + nif_phash2]. groups() -> [{G, [], api_repeaters()} || G <- api_groups()] @@ -2637,7 +2635,8 @@ nif_phash2(Config) -> lists:map( fun (Term) -> HashValue = erlang:phash2(Term), - NifHashValue = hash_nif(phash2, Term, 0), + Salt = random_uint32(), % phash2 should ignore salt + NifHashValue = hash_nif(phash2, Term, Salt), (HashValue =:= NifHashValue orelse ct:fail("Expected: ~p\nActual: ~p", [HashValue, NifHashValue])), @@ -2646,10 +2645,6 @@ nif_phash2(Config) -> Terms), test_bit_distribution_fitness(HashValues, HashValueBitSize, 0.05). -nif_phash2_salted(Config) -> - ensure_lib_loaded(Config), - test_salted_nif_hash(phash2). - test_salted_nif_hash(HashType) -> HashValueBitSize = nif_hash_result_bitsize(HashType), Terms = unique([random_term() || _ <- lists:seq(1, 5000)]), -- cgit v1.2.3 From eec41eeed17682a4e1f8ca15d92a2b469f0c39b8 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 21 Apr 2017 14:54:33 +0200 Subject: erts: Add erlang:list_to_port/1 debug bif --- erts/emulator/test/list_bif_SUITE.erl | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/list_bif_SUITE.erl b/erts/emulator/test/list_bif_SUITE.erl index 514dd2f412..9e1e351cd2 100644 --- a/erts/emulator/test/list_bif_SUITE.erl +++ b/erts/emulator/test/list_bif_SUITE.erl @@ -23,7 +23,7 @@ -export([all/0, suite/0]). -export([hd_test/1,tl_test/1,t_length/1,t_list_to_pid/1, - t_list_to_float/1,t_list_to_integer/1]). + t_list_to_port/1,t_list_to_float/1,t_list_to_integer/1]). suite() -> @@ -32,7 +32,7 @@ suite() -> all() -> - [hd_test, tl_test, t_length, t_list_to_pid, + [hd_test, tl_test, t_length, t_list_to_pid, t_list_to_port, t_list_to_float, t_list_to_integer]. %% Tests list_to_integer and string:to_integer @@ -106,10 +106,25 @@ t_list_to_pid(Config) when is_list(Config) -> {'EXIT', {badarg, _}} -> ok; Res -> - ct:fail("list_to_pid/1 with incorrect arg succeeded.~nResult: ~p", [Res]) + ct:fail("list_to_pid/1 with incorrect arg succeeded.~n" + "Result: ~p", [Res]) end, ok. +%% Test list_to_port/1 with correct and incorrect arguments. + +t_list_to_port(Config) when is_list(Config) -> + Me = hd(erlang:ports()), + MyListedPid = port_to_list(Me), + Me = list_to_port(MyListedPid), + case catch list_to_port(id("Incorrect list")) of + {'EXIT', {badarg, _}} -> + ok; + Res -> + ct:fail("list_to_port/1 with incorrect arg succeeded.~n" + "Result: ~p", [Res]) + end, + ok. %% Test list_to_float/1 with correct and incorrect arguments. -- cgit v1.2.3 From 83e20c62057ebc1d8064bf57b01be560cd244e1d Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Thu, 4 May 2017 15:42:21 +0200 Subject: Update copyright year --- erts/emulator/test/Makefile | 2 +- erts/emulator/test/binary_SUITE.erl | 2 +- erts/emulator/test/bs_match_int_SUITE.erl | 2 +- erts/emulator/test/call_trace_SUITE.erl | 2 +- erts/emulator/test/ddll_SUITE.erl | 2 +- erts/emulator/test/dirty_bif_SUITE.erl | 2 +- erts/emulator/test/dirty_nif_SUITE.erl | 2 +- erts/emulator/test/distribution_SUITE.erl | 2 +- erts/emulator/test/erl_link_SUITE.erl | 2 +- erts/emulator/test/erts_debug_SUITE.erl | 2 +- erts/emulator/test/estone_SUITE.erl | 2 +- erts/emulator/test/float_SUITE.erl | 2 +- erts/emulator/test/guard_SUITE.erl | 2 +- erts/emulator/test/hibernate_SUITE.erl | 2 +- erts/emulator/test/list_bif_SUITE.erl | 2 +- erts/emulator/test/match_spec_SUITE.erl | 2 +- erts/emulator/test/nif_SUITE.erl | 2 +- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 2 +- erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_drv_nif.h | 2 +- erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif.h | 2 +- erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif_api_funcs.h | 2 +- erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_drv_nif.h | 2 +- erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif.h | 2 +- erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif_api_funcs.h | 2 +- erts/emulator/test/nif_SUITE_data/nif_mod.c | 2 +- erts/emulator/test/node_container_SUITE.erl | 2 +- erts/emulator/test/num_bif_SUITE.erl | 2 +- erts/emulator/test/port_SUITE.erl | 2 +- erts/emulator/test/scheduler_SUITE.erl | 2 +- erts/emulator/test/smoke_test_SUITE.erl | 2 +- erts/emulator/test/statistics_SUITE.erl | 2 +- erts/emulator/test/system_info_SUITE.erl | 2 +- erts/emulator/test/time_SUITE.erl | 2 +- erts/emulator/test/z_SUITE.erl | 2 +- 34 files changed, 34 insertions(+), 34 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index ca81c9915e..2479ccc01f 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2016. All Rights Reserved. +# Copyright Ericsson AB 1997-2017. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl index 324730d562..355be7a36d 100644 --- a/erts/emulator/test/binary_SUITE.erl +++ b/erts/emulator/test/binary_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/bs_match_int_SUITE.erl b/erts/emulator/test/bs_match_int_SUITE.erl index 32bfa2f1fa..e913dc98b0 100644 --- a/erts/emulator/test/bs_match_int_SUITE.erl +++ b/erts/emulator/test/bs_match_int_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/call_trace_SUITE.erl b/erts/emulator/test/call_trace_SUITE.erl index e74631e916..1216863c51 100644 --- a/erts/emulator/test/call_trace_SUITE.erl +++ b/erts/emulator/test/call_trace_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/ddll_SUITE.erl b/erts/emulator/test/ddll_SUITE.erl index e7e518f82b..0b9f76a892 100644 --- a/erts/emulator/test/ddll_SUITE.erl +++ b/erts/emulator/test/ddll_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/dirty_bif_SUITE.erl b/erts/emulator/test/dirty_bif_SUITE.erl index 308323594d..b8361690e6 100644 --- a/erts/emulator/test/dirty_bif_SUITE.erl +++ b/erts/emulator/test/dirty_bif_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2014. All Rights Reserved. +%% Copyright Ericsson AB 2010-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/dirty_nif_SUITE.erl b/erts/emulator/test/dirty_nif_SUITE.erl index 5ba0d85ff3..f62f1e9dce 100644 --- a/erts/emulator/test/dirty_nif_SUITE.erl +++ b/erts/emulator/test/dirty_nif_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2016. All Rights Reserved. +%% Copyright Ericsson AB 2010-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl index 4f98cd6cee..434e729310 100644 --- a/erts/emulator/test/distribution_SUITE.erl +++ b/erts/emulator/test/distribution_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/erl_link_SUITE.erl b/erts/emulator/test/erl_link_SUITE.erl index 9258897764..5622cce980 100644 --- a/erts/emulator/test/erl_link_SUITE.erl +++ b/erts/emulator/test/erl_link_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2016. All Rights Reserved. +%% Copyright Ericsson AB 2001-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/erts_debug_SUITE.erl b/erts/emulator/test/erts_debug_SUITE.erl index c9c664de38..6aa7a445b5 100644 --- a/erts/emulator/test/erts_debug_SUITE.erl +++ b/erts/emulator/test/erts_debug_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2016. All Rights Reserved. +%% Copyright Ericsson AB 2005-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/estone_SUITE.erl b/erts/emulator/test/estone_SUITE.erl index 35f695ffe5..8b336b366d 100644 --- a/erts/emulator/test/estone_SUITE.erl +++ b/erts/emulator/test/estone_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2016. All Rights Reserved. +%% Copyright Ericsson AB 2002-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/float_SUITE.erl b/erts/emulator/test/float_SUITE.erl index ad33ad705b..4098aa9c6a 100644 --- a/erts/emulator/test/float_SUITE.erl +++ b/erts/emulator/test/float_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/guard_SUITE.erl b/erts/emulator/test/guard_SUITE.erl index 54ee710363..1a93a9f5c2 100644 --- a/erts/emulator/test/guard_SUITE.erl +++ b/erts/emulator/test/guard_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/hibernate_SUITE.erl b/erts/emulator/test/hibernate_SUITE.erl index 90693595a7..a20f306e04 100644 --- a/erts/emulator/test/hibernate_SUITE.erl +++ b/erts/emulator/test/hibernate_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2016. All Rights Reserved. +%% Copyright Ericsson AB 2003-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/list_bif_SUITE.erl b/erts/emulator/test/list_bif_SUITE.erl index 08574bff71..f95251943d 100644 --- a/erts/emulator/test/list_bif_SUITE.erl +++ b/erts/emulator/test/list_bif_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/match_spec_SUITE.erl b/erts/emulator/test/match_spec_SUITE.erl index 971a047309..eb189c2c33 100644 --- a/erts/emulator/test/match_spec_SUITE.erl +++ b/erts/emulator/test/match_spec_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 8ad11d3bf3..1eb58699b2 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2016. All Rights Reserved. +%% Copyright Ericsson AB 2010-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index a255c9f096..3747291e7e 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2009-2016. All Rights Reserved. + * Copyright Ericsson AB 2009-2017. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_drv_nif.h b/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_drv_nif.h index ea013a49a3..3e5435e353 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_drv_nif.h +++ b/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_drv_nif.h @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2010. All Rights Reserved. + * Copyright Ericsson AB 2010-2017. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in diff --git a/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif.h b/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif.h index 936f03bce1..4b2b7550e5 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif.h +++ b/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif.h @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2009-2010. All Rights Reserved. + * Copyright Ericsson AB 2009-2017. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in diff --git a/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif_api_funcs.h b/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif_api_funcs.h index ef4e9580b0..302973fcca 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif_api_funcs.h +++ b/erts/emulator/test/nif_SUITE_data/nif_api_2_0/erl_nif_api_funcs.h @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2009-2010. All Rights Reserved. + * Copyright Ericsson AB 2009-2017. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in diff --git a/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_drv_nif.h b/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_drv_nif.h index ea013a49a3..3e5435e353 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_drv_nif.h +++ b/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_drv_nif.h @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2010. All Rights Reserved. + * Copyright Ericsson AB 2010-2017. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in diff --git a/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif.h b/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif.h index 8006741a63..c3013b6b74 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif.h +++ b/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif.h @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2009-2013. All Rights Reserved. + * Copyright Ericsson AB 2009-2017. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in diff --git a/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif_api_funcs.h b/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif_api_funcs.h index 2f841645e1..92954403f3 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif_api_funcs.h +++ b/erts/emulator/test/nif_SUITE_data/nif_api_2_4/erl_nif_api_funcs.h @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2009-2013. All Rights Reserved. + * Copyright Ericsson AB 2009-2017. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.c b/erts/emulator/test/nif_SUITE_data/nif_mod.c index 04699d3327..885b8ebaf8 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_mod.c +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2009-2016. All Rights Reserved. + * Copyright Ericsson AB 2009-2017. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/node_container_SUITE.erl b/erts/emulator/test/node_container_SUITE.erl index 30518a5b27..8e9e3cb05a 100644 --- a/erts/emulator/test/node_container_SUITE.erl +++ b/erts/emulator/test/node_container_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2016. All Rights Reserved. +%% Copyright Ericsson AB 2002-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/num_bif_SUITE.erl b/erts/emulator/test/num_bif_SUITE.erl index f62eb0b430..1c76eb8019 100644 --- a/erts/emulator/test/num_bif_SUITE.erl +++ b/erts/emulator/test/num_bif_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index c117554f90..94ee9851dd 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl index 64e51e7d7c..8d71df65e7 100644 --- a/erts/emulator/test/scheduler_SUITE.erl +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2016. All Rights Reserved. +%% Copyright Ericsson AB 2008-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/smoke_test_SUITE.erl b/erts/emulator/test/smoke_test_SUITE.erl index 45b28b28a5..41bb07b84c 100644 --- a/erts/emulator/test/smoke_test_SUITE.erl +++ b/erts/emulator/test/smoke_test_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011-2016. All Rights Reserved. +%% Copyright Ericsson AB 2011-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/statistics_SUITE.erl b/erts/emulator/test/statistics_SUITE.erl index 729e86cb4f..3057905f4c 100644 --- a/erts/emulator/test/statistics_SUITE.erl +++ b/erts/emulator/test/statistics_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl index 6bd1eb1e1e..9c71f20279 100644 --- a/erts/emulator/test/system_info_SUITE.erl +++ b/erts/emulator/test/system_info_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2016. All Rights Reserved. +%% Copyright Ericsson AB 2005-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/time_SUITE.erl b/erts/emulator/test/time_SUITE.erl index c13d03bcc4..214a549a9d 100644 --- a/erts/emulator/test/time_SUITE.erl +++ b/erts/emulator/test/time_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/z_SUITE.erl b/erts/emulator/test/z_SUITE.erl index a90701c5d2..a2b267543f 100644 --- a/erts/emulator/test/z_SUITE.erl +++ b/erts/emulator/test/z_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2016. All Rights Reserved. +%% Copyright Ericsson AB 2006-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. -- cgit v1.2.3 From f95094d67e56a51bbdaadaf18625bb01c584bf2d Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 3 May 2017 20:33:13 +0200 Subject: erts: Fix code:is_module_native for local trace Local trace on first function in module made code:is_module_native/1 return true. Use new erts_is_function_native() to make a proper check. --- erts/emulator/test/trace_local_SUITE.erl | 1 + 1 file changed, 1 insertion(+) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/trace_local_SUITE.erl b/erts/emulator/test/trace_local_SUITE.erl index 5b65889f4a..1cbe6201c3 100644 --- a/erts/emulator/test/trace_local_SUITE.erl +++ b/erts/emulator/test/trace_local_SUITE.erl @@ -298,6 +298,7 @@ basic_test() -> setup([call]), NumMatches = erlang:trace_pattern({?MODULE,'_','_'},[],[local]), NumMatches = erlang:trace_pattern({?MODULE,'_','_'},[],[local]), + false = code:is_module_native(?MODULE), % got fooled by local trace erlang:trace_pattern({?MODULE,slave,'_'},false,[local]), [1,1,1,997] = apply_slave(?MODULE,exported_wrap,[1]), ?CT(?MODULE,exported_wrap,[1]), -- cgit v1.2.3 From 6962098f2ff7dcff5ce46364898815c685d0f0b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 4 May 2017 15:35:06 +0200 Subject: Extend hipe_SUITE to test exceptions and try/catch --- erts/emulator/test/hipe_SUITE.erl | 68 +++++++++++++++++++++++ erts/emulator/test/hipe_SUITE_data/trycatch_1.erl | 14 +++++ erts/emulator/test/hipe_SUITE_data/trycatch_2.erl | 10 ++++ erts/emulator/test/hipe_SUITE_data/trycatch_3.erl | 9 +++ 4 files changed, 101 insertions(+) create mode 100644 erts/emulator/test/hipe_SUITE_data/trycatch_1.erl create mode 100644 erts/emulator/test/hipe_SUITE_data/trycatch_2.erl create mode 100644 erts/emulator/test/hipe_SUITE_data/trycatch_3.erl (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/hipe_SUITE.erl b/erts/emulator/test/hipe_SUITE.erl index 0b44dd7fb7..5083f01f34 100644 --- a/erts/emulator/test/hipe_SUITE.erl +++ b/erts/emulator/test/hipe_SUITE.erl @@ -22,6 +22,7 @@ -export([all/0 ,t_copy_literals/1 ,t_purge/1 + ,t_trycatch/1 ]). all() -> @@ -29,6 +30,7 @@ all() -> undefined -> {skip, "HiPE is disabled"}; _ -> [t_copy_literals ,t_purge + ,t_trycatch ] end. @@ -118,3 +120,69 @@ t_purge(Config) when is_list(Config) -> call(Pid, Call) -> Pid ! {Call, self()}, receive {Pid, Res} -> Res end. + +t_trycatch(Config) -> + DataDir = proplists:get_value(data_dir, Config), + Files = ["trycatch_1.erl","trycatch_2.erl","trycatch_3.erl"], + Sources0 = [filename:join(DataDir, Src) || Src <- Files], + Sources = trycatch_combine(Sources0), + t_trycatch_1(Sources). + +t_trycatch_1([S|Ss]) -> + io:format("~p", [S]), + compile_and_load(S), + call_trycatch(try_catch), + call_trycatch(plain_catch), + io:nl(), + t_trycatch_1(Ss); +t_trycatch_1([]) -> + ok. + +trycatch_combine([N|Ns]) -> + Combined = trycatch_combine(Ns), + lists:append([[[{N,[]}|C],[{N,[native]},C]] || C <- Combined]); +trycatch_combine([]) -> + [[]]. + +call_trycatch(Func) -> + case do_call_trycatch(error, Func, {error,whatever}) of + {error,whatever,[{trycatch_3,three,1,_}|_]} -> + ok + end, + case do_call_trycatch(error, Func, fc) of + {error,function_clause,[{trycatch_3,three,[fc],_}|_]} -> + ok; + {error,function_clause,[{trycatch_3,three,1,_}|_]} -> + ok + end, + case do_call_trycatch(throw, Func, {throw,{a,b}}) of + {throw,{a,b},[{trycatch_3,three,1,_}|_]} -> + ok + end, + case do_call_trycatch(exit, Func, {exit,{a,b,c}}) of + {exit,{a,b,c},[{trycatch_3,three,1,_}|_]} -> + ok + end, + ok. + +do_call_trycatch(_Class, try_catch, Argument) -> + trycatch_1:one_try_catch(Argument); +do_call_trycatch(error, plain_catch, Argument) -> + {{'EXIT',{Reason,Stk}},Stk} = trycatch_1:one_plain_catch(Argument), + {error,Reason,Stk}; +do_call_trycatch(throw, plain_catch, Argument) -> + {Reason,Stk} = trycatch_1:one_plain_catch(Argument), + {throw,Reason,Stk}; +do_call_trycatch(exit, plain_catch, Argument) -> + {{'EXIT',Reason},Stk} = trycatch_1:one_plain_catch(Argument), + {exit,Reason,Stk}. + +compile_and_load(Sources) -> + _ = [begin + {ok,Mod,Bin} = compile:file(Src, [binary,report|Opts]), + code:purge(Mod), + code:delete(Mod), + code:purge(Mod), + {module,Mod} = code:load_binary(Mod, atom_to_list(Mod), Bin) + end || {Src,Opts} <- Sources], + ok. diff --git a/erts/emulator/test/hipe_SUITE_data/trycatch_1.erl b/erts/emulator/test/hipe_SUITE_data/trycatch_1.erl new file mode 100644 index 0000000000..702b14b5b9 --- /dev/null +++ b/erts/emulator/test/hipe_SUITE_data/trycatch_1.erl @@ -0,0 +1,14 @@ +-module(trycatch_1). +-export([one_try_catch/1,one_plain_catch/1]). + +one_try_catch(Term) -> + try + trycatch_2:two(Term) + catch + C:R -> + Stk = erlang:get_stacktrace(), + {C,R,Stk} + end. + +one_plain_catch(Term) -> + {catch trycatch_2:two(Term),erlang:get_stacktrace()}. diff --git a/erts/emulator/test/hipe_SUITE_data/trycatch_2.erl b/erts/emulator/test/hipe_SUITE_data/trycatch_2.erl new file mode 100644 index 0000000000..ffac420197 --- /dev/null +++ b/erts/emulator/test/hipe_SUITE_data/trycatch_2.erl @@ -0,0 +1,10 @@ +-module(trycatch_2). +-export([two/1]). + +two(Term) -> + Res = trycatch_3:three(Term), + foo(), + Res. + +foo() -> + ok. diff --git a/erts/emulator/test/hipe_SUITE_data/trycatch_3.erl b/erts/emulator/test/hipe_SUITE_data/trycatch_3.erl new file mode 100644 index 0000000000..578fa0e87e --- /dev/null +++ b/erts/emulator/test/hipe_SUITE_data/trycatch_3.erl @@ -0,0 +1,9 @@ +-module(trycatch_3). +-export([three/1]). + +three({error,Term}) -> + error(Term); +three({throw,Term}) -> + throw(Term); +three({exit,Term}) -> + exit(Term). -- cgit v1.2.3 From a1956797340a09cdf35d60cc6ccf255c9173d3f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 17 May 2017 11:43:11 +0200 Subject: Eliminate warning for variable 'Config' being unused --- erts/emulator/test/call_trace_SUITE.erl | 2 +- erts/emulator/test/driver_SUITE.erl | 2 +- erts/emulator/test/mtx_SUITE.erl | 2 +- erts/emulator/test/signal_SUITE.erl | 2 +- erts/emulator/test/statistics_SUITE.erl | 4 ++-- erts/emulator/test/trace_SUITE.erl | 4 ++-- erts/emulator/test/trace_meta_SUITE.erl | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/call_trace_SUITE.erl b/erts/emulator/test/call_trace_SUITE.erl index 1216863c51..95171d04ce 100644 --- a/erts/emulator/test/call_trace_SUITE.erl +++ b/erts/emulator/test/call_trace_SUITE.erl @@ -60,7 +60,7 @@ all() -> init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> Config. -end_per_testcase(_Func, Config) -> +end_per_testcase(_Func, _Config) -> %% Reloading the module will clear all trace patterns, and %% in a debug-compiled emulator run assertions of the counters %% for the number of traced exported functions in this module. diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl index 2fbf6eae61..e854a5f945 100644 --- a/erts/emulator/test/driver_SUITE.erl +++ b/erts/emulator/test/driver_SUITE.erl @@ -127,7 +127,7 @@ init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> 0 = element(1, erts_debug:get_internal_state(check_io_debug)), [{testcase, Case}|Config]. -end_per_testcase(Case, Config) -> +end_per_testcase(Case, _Config) -> erlang:display({end_per_testcase, Case}), 0 = element(1, erts_debug:get_internal_state(check_io_debug)), ok. diff --git a/erts/emulator/test/mtx_SUITE.erl b/erts/emulator/test/mtx_SUITE.erl index 12928ed6d8..0d6ab5cdb2 100644 --- a/erts/emulator/test/mtx_SUITE.erl +++ b/erts/emulator/test/mtx_SUITE.erl @@ -97,7 +97,7 @@ init_per_testcase(_Case, Config) -> wait_deallocations(), Config. -end_per_testcase(_Func, Config) -> +end_per_testcase(_Func, _Config) -> ok. wait_deallocations() -> diff --git a/erts/emulator/test/signal_SUITE.erl b/erts/emulator/test/signal_SUITE.erl index 7e516176f7..d788360812 100644 --- a/erts/emulator/test/signal_SUITE.erl +++ b/erts/emulator/test/signal_SUITE.erl @@ -53,7 +53,7 @@ init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> available_internal_state(true), [{testcase, Func}|Config]. -end_per_testcase(_Func, Config) -> +end_per_testcase(_Func, _Config) -> ok. init_per_suite(Config) -> diff --git a/erts/emulator/test/statistics_SUITE.erl b/erts/emulator/test/statistics_SUITE.erl index 3057905f4c..0cea941687 100644 --- a/erts/emulator/test/statistics_SUITE.erl +++ b/erts/emulator/test/statistics_SUITE.erl @@ -396,7 +396,7 @@ msb_swt_hog(false) -> count(1000000), msb_swt_hog(false). -msb_scheduler_wall_time(Config) -> +msb_scheduler_wall_time(_Config) -> erlang:system_flag(scheduler_wall_time, true), Dirty = erlang:system_info(dirty_cpu_schedulers) /= 0, Hogs = lists:map(fun (_) -> @@ -493,7 +493,7 @@ badarg(Config) when is_list(Config) -> tok_loop() -> tok_loop(). -run_queues_lengths_active_tasks(Config) -> +run_queues_lengths_active_tasks(_Config) -> TokLoops = lists:map(fun (_) -> spawn_opt(fun () -> tok_loop() diff --git a/erts/emulator/test/trace_SUITE.erl b/erts/emulator/test/trace_SUITE.erl index f846b0f4b9..643c2e0472 100644 --- a/erts/emulator/test/trace_SUITE.erl +++ b/erts/emulator/test/trace_SUITE.erl @@ -733,7 +733,7 @@ set_on_first_spawn(Config) when is_list(Config) -> %% Tests trace(Pid, How, [set_on_link]). -set_on_link(Config) -> +set_on_link(_Config) -> Listener = fun_spawn(fun process/0), %% Create and trace a process with the set_on_link flag. @@ -756,7 +756,7 @@ set_on_link(Config) -> %% Tests trace(Pid, How, [set_on_first_spawn]). -set_on_first_link(Config) -> +set_on_first_link(_Config) -> ct:timetrap({seconds, 10}), Listener = fun_spawn(fun process/0), diff --git a/erts/emulator/test/trace_meta_SUITE.erl b/erts/emulator/test/trace_meta_SUITE.erl index b6a6fd5404..ef58978749 100644 --- a/erts/emulator/test/trace_meta_SUITE.erl +++ b/erts/emulator/test/trace_meta_SUITE.erl @@ -74,7 +74,7 @@ config(priv_dir,_) -> init_per_testcase(_Case, Config) -> Config. -end_per_testcase(_Case, Config) -> +end_per_testcase(_Case, _Config) -> shutdown(), ok. -- cgit v1.2.3 From caf36b503f6c43494a89e196a59aa69ad3156087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 17 May 2017 11:48:07 +0200 Subject: code_SUITE: Remove unused functions --- erts/emulator/test/code_SUITE.erl | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index d07166ed98..35f7baf2cf 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -229,27 +229,6 @@ multi_proc_purge(Config) when is_list(Config) -> Pid9, Pid10, Pid11, Pid12, Pid13, Pid14, Pid15, Pid16]), ok. -body(F, Fakes) -> - receive - jog -> - 40 = F(3), - erlang:garbage_collect(), - body(F, Fakes); - drop_funs -> - dropped_body() - end. - -dropped_body() -> - receive - X -> exit(X) - end. - -gc() -> - erlang:garbage_collect(), - gc1(). -gc1() -> ok. - - %% Test the erlang:check_old_code/1 BIF. t_check_old_code(Config) when is_list(Config) -> Data = proplists:get_value(data_dir, Config), -- cgit v1.2.3 From 32ea8ba368c455afba07afd85bed6fb57879f56d Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Thu, 18 May 2017 20:42:04 +0200 Subject: Make statistics/1 aware of dirty run-queues and tasks --- erts/emulator/test/statistics_SUITE.erl | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/statistics_SUITE.erl b/erts/emulator/test/statistics_SUITE.erl index 3057905f4c..65188b6e26 100644 --- a/erts/emulator/test/statistics_SUITE.erl +++ b/erts/emulator/test/statistics_SUITE.erl @@ -502,20 +502,37 @@ run_queues_lengths_active_tasks(Config) -> end, lists:seq(1,10)), + + TRQLs0 = statistics(total_run_queue_lengths), + TRQLAs0 = statistics(total_run_queue_lengths_all), TATs0 = statistics(total_active_tasks), + TATAs0 = statistics(total_active_tasks_all), true = is_integer(TRQLs0), true = is_integer(TATs0), true = TRQLs0 >= 0, + true = TRQLAs0 >= 0, true = TATs0 >= 11, + true = TATAs0 >= 11, NoScheds = erlang:system_info(schedulers), + {DefRqs, + AllRqs} = case erlang:system_info(dirty_cpu_schedulers) of + 0 -> {NoScheds, NoScheds}; + _ -> {NoScheds+1, NoScheds+2} + end, RQLs0 = statistics(run_queue_lengths), + RQLAs0 = statistics(run_queue_lengths_all), ATs0 = statistics(active_tasks), - NoScheds = length(RQLs0), - NoScheds = length(ATs0), + ATAs0 = statistics(active_tasks_all), + DefRqs = length(RQLs0), + AllRqs = length(RQLAs0), + DefRqs = length(ATs0), + AllRqs = length(ATAs0), true = lists:sum(RQLs0) >= 0, + true = lists:sum(RQLAs0) >= 0, true = lists:sum(ATs0) >= 11, + true = lists:sum(ATAs0) >= 11, SO = erlang:system_flag(schedulers_online, 1), @@ -531,8 +548,8 @@ run_queues_lengths_active_tasks(Config) -> RQLs1 = statistics(run_queue_lengths), ATs1 = statistics(active_tasks), - NoScheds = length(RQLs1), - NoScheds = length(ATs1), + DefRqs = length(RQLs1), + DefRqs = length(ATs1), TRQLs2 = lists:sum(RQLs1), TATs2 = lists:sum(ATs1), true = TRQLs2 >= 10, -- cgit v1.2.3 From e606eae1325a9f73140ab309d5dbbb7cdb589a04 Mon Sep 17 00:00:00 2001 From: Ted Burghart Date: Mon, 22 May 2017 15:36:09 -0400 Subject: Add enif_whereis_...() functions #### Why do we need this new feature? There are cases when a NIF needs to send a message, using `enif_send()`, to a long-lived process with a registered name. A common use-case is logging, where asynchronous fire-and-forget messages are the norm. There can also be cases where a yielding or dirty NIF or background thread may request a callback from a service with additional information it needs to complete its operation, yielding or waiting (with suitable timeouts, etc) until its state has been updated through the NIF module's API. NIFs can only send messages to pids, and the lack of name resolution leaves a complicated dance between separate monitoring processes and the NIF as the only way to keep a NIF informed of the whereabouts of such long-lived processes. Providing a reliable, built-in facility for NIFs to resolve process (or port) names simplifies these use cases considerably. #### Risks or uncertain artifacts? Testing has not exposed any significant risk. The implementation behaves as expected on regular and dirty scheduler threads as well as non-scheduler threads. By constraining the `enif_whereis_...()` functions to their minimal scopes and using patterns consistent with related functions, the implementation, testing, and maintenance burden is low. The API and behavior of existing functions is unchanged. #### How did you solve it? While extending `enif_send()` to operate on a pid or an atom (as `erlang:send/2` does) was attractive, it would have entailed changing the type of its `to_pid` parameter and thereby breaking backward compatibility. The same consideration applies to `enif_port_command()`. That leaves a choice between 1, 2, or 3 new functions: 1. `enif_whereis()` 2. `enif_whereis_pid()` and `enif_whereis_port()` 3. All of the above. While option (1), directly mimicking the behavior of `erlang:whereis/1`, is appealing, it poses potential problems if `pid()` or `port()` are subsequently implemented as non-integral types that must be bound to an owning `ErlNifEnv` instance. Therefore, option (2) has been chosen to use `ErlNifPid`/`ErlNifPort` structures in the API to maintain proper term ownership semantics. --- erts/emulator/test/dirty_nif_SUITE.erl | 140 ++++++++++- .../test/dirty_nif_SUITE_data/Makefile.src | 2 +- .../test/dirty_nif_SUITE_data/dirty_nif_SUITE.c | 172 +++++++++++++- erts/emulator/test/dirty_nif_SUITE_data/echo_drv.c | 62 +++++ erts/emulator/test/nif_SUITE.erl | 173 +++++++++++++- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 262 ++++++++++++++++++++- 6 files changed, 804 insertions(+), 7 deletions(-) create mode 100644 erts/emulator/test/dirty_nif_SUITE_data/echo_drv.c (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/dirty_nif_SUITE.erl b/erts/emulator/test/dirty_nif_SUITE.erl index f62f1e9dce..13806fd5c4 100644 --- a/erts/emulator/test/dirty_nif_SUITE.erl +++ b/erts/emulator/test/dirty_nif_SUITE.erl @@ -34,7 +34,8 @@ dirty_scheduler_exit/1, dirty_call_while_terminated/1, dirty_heap_access/1, dirty_process_info/1, dirty_process_register/1, dirty_process_trace/1, - code_purge/1, dirty_nif_send_traced/1]). + code_purge/1, dirty_nif_send_traced/1, + nif_whereis/1, nif_whereis_parallel/1, nif_whereis_proxy/1]). -define(nif_stub,nif_stub_error(?LINE)). @@ -51,7 +52,9 @@ all() -> dirty_process_register, dirty_process_trace, code_purge, - dirty_nif_send_traced]. + dirty_nif_send_traced, + nif_whereis, + nif_whereis_parallel]. init_per_suite(Config) -> case erlang:system_info(dirty_cpu_schedulers) of @@ -531,6 +534,137 @@ mcall(Node, Funs) -> end end, Refs). +%% Test enif_whereis_... +%% These tests are mostly identical to their counterparts in nif_SUITE.erl, +%% with just name and count changes in the first few lines. + +nif_whereis(Config) when is_list(Config) -> + erl_ddll:try_load(?config(data_dir, Config), echo_drv, []), + + RegName = dirty_nif_whereis_test_thing, + undefined = erlang:whereis(RegName), + false = whereis_term(pid, RegName), + + Mgr = self(), + Ref = make_ref(), + ProcMsg = {Ref, ?LINE}, + PortMsg = ?MODULE_STRING " whereis hello\n", + + {Pid, Mon} = spawn_monitor(?MODULE, nif_whereis_proxy, [Ref]), + true = register(RegName, Pid), + Pid = erlang:whereis(RegName), + Pid = whereis_term(pid, RegName), + false = whereis_term(port, RegName), + false = whereis_term(pid, [RegName]), + + ok = whereis_send(pid, RegName, {forward, Mgr, ProcMsg}), + ok = receive ProcMsg -> ok end, + + Pid ! {Ref, quit}, + ok = receive {'DOWN', Mon, process, Pid, normal} -> ok end, + undefined = erlang:whereis(RegName), + false = whereis_term(pid, RegName), + + Port = open_port({spawn, echo_drv}, [eof]), + true = register(RegName, Port), + Port = erlang:whereis(RegName), + Port = whereis_term(port, RegName), + false = whereis_term(pid, RegName), + false = whereis_term(port, [RegName]), + + ok = whereis_send(port, RegName, PortMsg), + ok = receive {Port, {data, PortMsg}} -> ok end, + + port_close(Port), + undefined = erlang:whereis(RegName), + false = whereis_term(port, RegName), + ok. + +nif_whereis_parallel(Config) when is_list(Config) -> + + %% try to be at least a little asymetric + NProcs = trunc(3.5 * erlang:system_info(schedulers)), + NSeq = lists:seq(1, NProcs), + Names = [list_to_atom("dirty_nif_whereis_proc_" ++ integer_to_list(N)) + || N <- NSeq], + Mgr = self(), + Ref = make_ref(), + + NotReg = fun(Name) -> + erlang:whereis(Name) == undefined + end, + PidReg = fun({Name, Pid, _Mon}) -> + erlang:whereis(Name) == Pid andalso whereis_term(pid, Name) == Pid + end, + RecvDown = fun({_Name, Pid, Mon}) -> + receive {'DOWN', Mon, process, Pid, normal} -> true + after 1500 -> false end + end, + RecvNum = fun(N) -> + receive {N, Ref} -> true + after 1500 -> false end + end, + + true = lists:all(NotReg, Names), + + %% {Name, Pid, Mon} + Procs = lists:map( + fun(N) -> + Name = lists:nth(N, Names), + Prev = lists:nth((if N == 1 -> NProcs; true -> (N - 1) end), Names), + Next = lists:nth((if N == NProcs -> 1; true -> (N + 1) end), Names), + {Pid, Mon} = spawn_monitor( + ?MODULE, nif_whereis_proxy, [{N, Ref, Mgr, [Prev, Next]}]), + true = register(Name, Pid), + {Name, Pid, Mon} + end, NSeq), + + true = lists:all(PidReg, Procs), + + %% tell them all to 'fire' as fast as we can + [P ! {Ref, send_proc} || {_, P, _} <- Procs], + + %% each gets forwarded through two processes + true = lists:all(RecvNum, NSeq), + true = lists:all(RecvNum, NSeq), + + %% tell them all to 'quit' by name + [N ! {Ref, quit} || {N, _, _} <- Procs], + true = lists:all(RecvDown, Procs), + true = lists:all(NotReg, Names), + ok. + +%% exported to be spawned by MFA by whereis tests +nif_whereis_proxy({N, Ref, Mgr, Targets} = Args) -> + receive + {forward, To, Data} -> + To ! Data, + nif_whereis_proxy(Args); + {Ref, quit} -> + ok; + {Ref, send_port} -> + Msg = ?MODULE_STRING " whereis " ++ integer_to_list(N) ++ "\n", + lists:foreach( + fun(T) -> + ok = whereis_send(port, T, Msg) + end, Targets), + nif_whereis_proxy(Args); + {Ref, send_proc} -> + lists:foreach( + fun(T) -> + ok = whereis_send(pid, T, {forward, Mgr, {N, Ref}}) + end, Targets), + nif_whereis_proxy(Args) + end; +nif_whereis_proxy(Ref) -> + receive + {forward, To, Data} -> + To ! Data, + nif_whereis_proxy(Ref); + {Ref, quit} -> + ok + end. + %% The NIFs: lib_loaded() -> false. call_dirty_nif(_,_,_) -> ?nif_stub. @@ -542,6 +676,8 @@ dirty_call_while_terminated_nif(_) -> ?nif_stub. dirty_sleeper() -> ?nif_stub. dirty_sleeper(_) -> ?nif_stub. dirty_heap_access_nif(_) -> ?nif_stub. +whereis_term(_Type,_Name) -> ?nif_stub. +whereis_send(_Type,_Name,_Msg) -> ?nif_stub. nif_stub_error(Line) -> exit({nif_not_loaded,module,?MODULE,line,Line}). diff --git a/erts/emulator/test/dirty_nif_SUITE_data/Makefile.src b/erts/emulator/test/dirty_nif_SUITE_data/Makefile.src index e9301753b0..4462afd815 100644 --- a/erts/emulator/test/dirty_nif_SUITE_data/Makefile.src +++ b/erts/emulator/test/dirty_nif_SUITE_data/Makefile.src @@ -1,6 +1,6 @@ NIF_LIBS = dirty_nif_SUITE@dll@ -all: $(NIF_LIBS) +all: $(NIF_LIBS) echo_drv@dll@ @SHLIB_RULES@ diff --git a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c index caf99c952f..1ab39466db 100644 --- a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c +++ b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c @@ -25,8 +25,35 @@ #include #endif +/* + * Hack to get around this function missing from the NIF API. + * TODO: Add this function/macro in the appropriate place, probably with + * enif_make_pid() in erl_nif_api_funcs.h + */ +#ifndef enif_make_port +#define enif_make_port(ENV, PORT) ((void)(ENV),(const ERL_NIF_TERM)((PORT)->port_id)) +#endif + +static ERL_NIF_TERM atom_badarg; +static ERL_NIF_TERM atom_error; +static ERL_NIF_TERM atom_false; +static ERL_NIF_TERM atom_lookup; +static ERL_NIF_TERM atom_ok; +static ERL_NIF_TERM atom_pid; +static ERL_NIF_TERM atom_port; +static ERL_NIF_TERM atom_send; + static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { + atom_badarg = enif_make_atom(env, "badarg"); + atom_error = enif_make_atom(env, "error"); + atom_false = enif_make_atom(env,"false"); + atom_lookup = enif_make_atom(env, "lookup"); + atom_ok = enif_make_atom(env,"ok"); + atom_pid = enif_make_atom(env, "pid"); + atom_port = enif_make_atom(env, "port"); + atom_send = enif_make_atom(env, "send"); + return 0; } @@ -257,6 +284,147 @@ static ERL_NIF_TERM dirty_heap_access_nif(ErlNifEnv* env, int argc, const ERL_NI return res; } +/* + * enif_whereis_... tests + * subset of the functions in nif_SUITE.c + */ + +enum { + /* results */ + WHEREIS_SUCCESS, + WHEREIS_ERROR_TYPE, + WHEREIS_ERROR_LOOKUP, + WHEREIS_ERROR_SEND, + /* types */ + WHEREIS_LOOKUP_PID, /* enif_whereis_pid() */ + WHEREIS_LOOKUP_PORT /* enif_whereis_port() */ +}; + +typedef union { + ErlNifPid pid; + ErlNifPort port; +} whereis_term_data_t; + +static int whereis_type(ERL_NIF_TERM type) +{ + if (enif_is_identical(type, atom_pid)) + return WHEREIS_LOOKUP_PID; + + if (enif_is_identical(type, atom_port)) + return WHEREIS_LOOKUP_PORT; + + return WHEREIS_ERROR_TYPE; +} + +static int whereis_lookup_internal( + ErlNifEnv* env, int type, ERL_NIF_TERM name, whereis_term_data_t* out) +{ + if (type == WHEREIS_LOOKUP_PID) + return enif_whereis_pid(env, name, & out->pid) + ? WHEREIS_SUCCESS : WHEREIS_ERROR_LOOKUP; + + if (type == WHEREIS_LOOKUP_PORT) + return enif_whereis_port(env, name, & out->port) + ? WHEREIS_SUCCESS : WHEREIS_ERROR_LOOKUP; + + return WHEREIS_ERROR_TYPE; +} + +static int whereis_send_internal( + ErlNifEnv* env, int type, whereis_term_data_t* to, ERL_NIF_TERM msg) +{ + if (type == WHEREIS_LOOKUP_PID) + return enif_send(env, & to->pid, NULL, msg) + ? WHEREIS_SUCCESS : WHEREIS_ERROR_SEND; + + if (type == WHEREIS_LOOKUP_PORT) + return enif_port_command(env, & to->port, NULL, msg) + ? WHEREIS_SUCCESS : WHEREIS_ERROR_SEND; + + return WHEREIS_ERROR_TYPE; +} + +static int whereis_lookup_term( + ErlNifEnv* env, int type, ERL_NIF_TERM name, ERL_NIF_TERM* out) +{ + whereis_term_data_t res; + int rc = whereis_lookup_internal(env, type, name, &res); + if (rc == WHEREIS_SUCCESS) { + switch (type) { + case WHEREIS_LOOKUP_PID: + *out = enif_make_pid(env, & res.pid); + break; + case WHEREIS_LOOKUP_PORT: + *out = enif_make_port(env, & res.port); + break; + default: + rc = WHEREIS_ERROR_TYPE; + break; + } + } + return rc; +} + +static ERL_NIF_TERM whereis_result_term(ErlNifEnv* env, int result) +{ + ERL_NIF_TERM err; + switch (result) + { + case WHEREIS_SUCCESS: + return atom_ok; + case WHEREIS_ERROR_LOOKUP: + err = atom_lookup; + break; + case WHEREIS_ERROR_SEND: + err = atom_send; + break; + case WHEREIS_ERROR_TYPE: + err = atom_badarg; + break; + default: + err = enif_make_int(env, -result); + break; + } + return enif_make_tuple2(env, atom_error, err); +} + +/* whereis_term(Type, Name) -> pid() | port() | false */ +static ERL_NIF_TERM +whereis_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ERL_NIF_TERM ret; + int type, rc; + + if (argc != 2) /* allow non-atom name for testing */ + return enif_make_badarg(env); + + if ((type = whereis_type(argv[0])) == WHEREIS_ERROR_TYPE) + return enif_make_badarg(env); + + rc = whereis_lookup_term(env, type, argv[1], &ret); + return (rc == WHEREIS_SUCCESS) ? ret : atom_false; +} + +/* whereis_send(Type, Name, Message) -> ok | {error, Reason} */ +static ERL_NIF_TERM +whereis_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + whereis_term_data_t to; + int type, rc; + + if (argc != 3 || !enif_is_atom(env, argv[1])) + return enif_make_badarg(env); + + if ((type = whereis_type(argv[0])) == WHEREIS_ERROR_TYPE) + return enif_make_badarg(env); + + rc = whereis_lookup_internal(env, type, argv[1], & to); + if (rc == WHEREIS_SUCCESS) + rc = whereis_send_internal(env, type, & to, argv[2]); + + return whereis_result_term(env, rc); +} + static ErlNifFunc nif_funcs[] = { @@ -269,7 +437,9 @@ static ErlNifFunc nif_funcs[] = {"dirty_sleeper", 0, dirty_sleeper, ERL_NIF_DIRTY_JOB_IO_BOUND}, {"dirty_sleeper", 1, dirty_sleeper, ERL_NIF_DIRTY_JOB_CPU_BOUND}, {"dirty_call_while_terminated_nif", 1, dirty_call_while_terminated_nif, ERL_NIF_DIRTY_JOB_CPU_BOUND}, - {"dirty_heap_access_nif", 1, dirty_heap_access_nif, ERL_NIF_DIRTY_JOB_CPU_BOUND} + {"dirty_heap_access_nif", 1, dirty_heap_access_nif, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"whereis_send", 3, whereis_send, ERL_NIF_DIRTY_JOB_IO_BOUND}, + {"whereis_term", 2, whereis_term, ERL_NIF_DIRTY_JOB_CPU_BOUND} }; ERL_NIF_INIT(dirty_nif_SUITE,nif_funcs,load,NULL,NULL,NULL) diff --git a/erts/emulator/test/dirty_nif_SUITE_data/echo_drv.c b/erts/emulator/test/dirty_nif_SUITE_data/echo_drv.c new file mode 100644 index 0000000000..2b3510c641 --- /dev/null +++ b/erts/emulator/test/dirty_nif_SUITE_data/echo_drv.c @@ -0,0 +1,62 @@ +#include +#include "erl_driver.h" + +static ErlDrvPort erlang_port; +static ErlDrvData echo_start(ErlDrvPort, char *); +static void from_erlang(ErlDrvData, char*, ErlDrvSizeT); +static ErlDrvSSizeT echo_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, unsigned *ret_flags); +static ErlDrvEntry echo_driver_entry = { + NULL, /* Init */ + echo_start, + NULL, /* Stop */ + from_erlang, + NULL, /* Ready input */ + NULL, /* Ready output */ + "echo_drv", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + echo_call, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL +}; + +DRIVER_INIT(echo_drv) +{ + return &echo_driver_entry; +} + +static ErlDrvData +echo_start(ErlDrvPort port, char *buf) +{ + return (ErlDrvData) port; +} + +static void +from_erlang(ErlDrvData data, char *buf, ErlDrvSizeT count) +{ + driver_output((ErlDrvPort) data, buf, count); +} + +static ErlDrvSSizeT +echo_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, + unsigned *ret_flags) +{ + *rbuf = buf; + *ret_flags |= DRIVER_CALL_KEEP_BUFFER; + return len; +} + diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 1eb58699b2..c8bd9f81f8 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -59,7 +59,9 @@ nif_snprintf/1, nif_internal_hash/1, nif_internal_hash_salted/1, - nif_phash2/1 + nif_phash2/1, + nif_whereis/1, nif_whereis_parallel/1, + nif_whereis_threaded/1, nif_whereis_proxy/1 ]). -export([many_args_100/100]). @@ -96,7 +98,8 @@ all() -> nif_snprintf, nif_internal_hash, nif_internal_hash_salted, - nif_phash2]. + nif_phash2, + nif_whereis, nif_whereis_parallel, nif_whereis_threaded]. groups() -> [{G, [], api_repeaters()} || G <- api_groups()] @@ -134,6 +137,11 @@ init_per_testcase(hipe, Config) -> undefined -> {skip, "HiPE is disabled"}; _ -> Config end; +init_per_testcase(nif_whereis_threaded, Config) -> + case erlang:system_info(threads) of + true -> Config; + false -> {skip, "No thread support"} + end; init_per_testcase(select, Config) -> case os:type() of {win32,_} -> @@ -2765,6 +2773,161 @@ random_pid() -> Processes = erlang:processes(), lists:nth(rand:uniform(length(Processes)), Processes). +%% Test enif_whereis_... + +nif_whereis(Config) when is_list(Config) -> + ensure_lib_loaded(Config), + + RegName = nif_whereis_test_thing, + undefined = erlang:whereis(RegName), + false = whereis_term(pid, RegName), + + Mgr = self(), + Ref = make_ref(), + ProcMsg = {Ref, ?LINE}, + PortMsg = ?MODULE_STRING " whereis hello\n", + + {Pid, Mon} = spawn_monitor(?MODULE, nif_whereis_proxy, [Ref]), + true = register(RegName, Pid), + Pid = erlang:whereis(RegName), + Pid = whereis_term(pid, RegName), + false = whereis_term(port, RegName), + false = whereis_term(pid, [RegName]), + + ok = whereis_send(pid, RegName, {forward, Mgr, ProcMsg}), + ok = receive ProcMsg -> ok end, + + Pid ! {Ref, quit}, + ok = receive {'DOWN', Mon, process, Pid, normal} -> ok end, + undefined = erlang:whereis(RegName), + false = whereis_term(pid, RegName), + + Port = open_port({spawn, echo_drv}, [eof]), + true = register(RegName, Port), + Port = erlang:whereis(RegName), + Port = whereis_term(port, RegName), + false = whereis_term(pid, RegName), + false = whereis_term(port, [RegName]), + + ok = whereis_send(port, RegName, PortMsg), + ok = receive {Port, {data, PortMsg}} -> ok end, + + port_close(Port), + undefined = erlang:whereis(RegName), + false = whereis_term(port, RegName), + ok. + +nif_whereis_parallel(Config) when is_list(Config) -> + ensure_lib_loaded(Config), + + %% try to be at least a little asymetric + NProcs = trunc(3.7 * erlang:system_info(schedulers)), + NSeq = lists:seq(1, NProcs), + Names = [list_to_atom("nif_whereis_proc_" ++ integer_to_list(N)) + || N <- NSeq], + Mgr = self(), + Ref = make_ref(), + + NotReg = fun(Name) -> + erlang:whereis(Name) == undefined + end, + PidReg = fun({Name, Pid, _Mon}) -> + erlang:whereis(Name) == Pid andalso whereis_term(pid, Name) == Pid + end, + RecvDown = fun({_Name, Pid, Mon}) -> + receive {'DOWN', Mon, process, Pid, normal} -> true + after 1500 -> false end + end, + RecvNum = fun(N) -> + receive {N, Ref} -> true + after 1500 -> false end + end, + + true = lists:all(NotReg, Names), + + %% {Name, Pid, Mon} + Procs = lists:map( + fun(N) -> + Name = lists:nth(N, Names), + Prev = lists:nth((if N == 1 -> NProcs; true -> (N - 1) end), Names), + Next = lists:nth((if N == NProcs -> 1; true -> (N + 1) end), Names), + {Pid, Mon} = spawn_monitor( + ?MODULE, nif_whereis_proxy, [{N, Ref, Mgr, [Prev, Next]}]), + true = register(Name, Pid), + {Name, Pid, Mon} + end, NSeq), + + true = lists:all(PidReg, Procs), + + %% tell them all to 'fire' as fast as we can + [P ! {Ref, send_proc} || {_, P, _} <- Procs], + + %% each gets forwarded through two processes + true = lists:all(RecvNum, NSeq), + true = lists:all(RecvNum, NSeq), + + %% tell them all to 'quit' by name + [N ! {Ref, quit} || {N, _, _} <- Procs], + true = lists:all(RecvDown, Procs), + true = lists:all(NotReg, Names), + ok. + +nif_whereis_threaded(Config) when is_list(Config) -> + ensure_lib_loaded(Config), + + RegName = nif_whereis_test_threaded, + undefined = erlang:whereis(RegName), + + Ref = make_ref(), + {Pid, Mon} = spawn_monitor(?MODULE, nif_whereis_proxy, [Ref]), + true = register(RegName, Pid), + + {ok, ProcThr} = whereis_thd_lookup(pid, RegName), + {ok, Pid} = whereis_thd_result(ProcThr), + + Pid ! {Ref, quit}, + ok = receive {'DOWN', Mon, process, Pid, normal} -> ok end, + + Port = open_port({spawn, echo_drv}, [eof]), + true = register(RegName, Port), + + {ok, PortThr} = whereis_thd_lookup(port, RegName), + {ok, Port} = whereis_thd_result(PortThr), + + port_close(Port), + ok. + +%% exported to be spawned by MFA by whereis tests +nif_whereis_proxy({N, Ref, Mgr, Targets} = Args) -> + receive + {forward, To, Data} -> + To ! Data, + nif_whereis_proxy(Args); + {Ref, quit} -> + ok; + {Ref, send_port} -> + Msg = ?MODULE_STRING " whereis " ++ integer_to_list(N) ++ "\n", + lists:foreach( + fun(T) -> + ok = whereis_send(port, T, Msg) + end, Targets), + nif_whereis_proxy(Args); + {Ref, send_proc} -> + lists:foreach( + fun(T) -> + ok = whereis_send(pid, T, {forward, Mgr, {N, Ref}}) + end, Targets), + nif_whereis_proxy(Args) + end; +nif_whereis_proxy(Ref) -> + receive + {forward, To, Data} -> + To ! Data, + nif_whereis_proxy(Ref); + {Ref, quit} -> + ok + end. + %% The NIFs: lib_version() -> undefined. call_history() -> ?nif_stub. @@ -2839,6 +3002,12 @@ demonitor_process_nif(_,_) -> ?nif_stub. compare_monitors_nif(_,_) -> ?nif_stub. monitor_frenzy_nif(_,_,_,_) -> ?nif_stub. +%% whereis +whereis_send(_Type,_Name,_Msg) -> ?nif_stub. +whereis_term(_Type,_Name) -> ?nif_stub. +whereis_thd_lookup(_Type,_Name) -> ?nif_stub. +whereis_thd_result(_Thd) -> ?nif_stub. + %% maps is_map_nif(_) -> ?nif_stub. get_map_size_nif(_) -> ?nif_stub. diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 3747291e7e..003a0f2929 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -52,6 +52,15 @@ static ErlNifMutex* dbg_trace_lock; #define DBG_TRACE4(FMT, A, B, C, D) #endif +/* + * Hack to get around this function missing from the NIF API. + * TODO: Add this function/macro in the appropriate place, probably with + * enif_make_pid() in erl_nif_api_funcs.h + */ +#ifndef enif_make_port +#define enif_make_port(ENV, PORT) ((void)(ENV),(const ERL_NIF_TERM)((PORT)->port_id)) +#endif + static int static_cntA; /* zero by default */ static int static_cntB = NIF_SUITE_LIB_VER * 100; @@ -76,6 +85,11 @@ static ERL_NIF_TERM atom_stats; static ERL_NIF_TERM atom_done; static ERL_NIF_TERM atom_stop; static ERL_NIF_TERM atom_null; +static ERL_NIF_TERM atom_pid; +static ERL_NIF_TERM atom_port; +static ERL_NIF_TERM atom_send; +static ERL_NIF_TERM atom_lookup; +static ERL_NIF_TERM atom_badarg; typedef struct { @@ -170,6 +184,9 @@ static ErlNifResourceTypeInit frenzy_rt_init = { frenzy_resource_down }; +static ErlNifResourceType* whereis_resource_type; +static void whereis_thread_resource_dtor(ErlNifEnv* env, void* obj); + static int get_pointer(ErlNifEnv* env, ERL_NIF_TERM term, void** pp) { ErlNifBinary bin; @@ -223,6 +240,9 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) &frenzy_rt_init, ERL_NIF_RT_CREATE, NULL); + whereis_resource_type = enif_open_resource_type(env, NULL, "nif_SUITE.whereis", + whereis_thread_resource_dtor, ERL_NIF_RT_CREATE, NULL); + atom_false = enif_make_atom(env,"false"); atom_true = enif_make_atom(env,"true"); atom_self = enif_make_atom(env,"self"); @@ -244,6 +264,11 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_done = enif_make_atom(env,"done"); atom_stop = enif_make_atom(env,"stop"); atom_null = enif_make_atom(env,"null"); + atom_pid = enif_make_atom(env, "pid"); + atom_port = enif_make_atom(env, "port"); + atom_send = enif_make_atom(env, "send"); + atom_lookup = enif_make_atom(env, "lookup"); + atom_badarg = enif_make_atom(env, "badarg"); *priv_data = data; return 0; @@ -1137,6 +1162,237 @@ static void fill(void* dst, unsigned bytes, int seed) } } +/* enif_whereis_... tests */ + +enum { + /* results */ + WHEREIS_SUCCESS, + WHEREIS_ERROR_TYPE, + WHEREIS_ERROR_LOOKUP, + WHEREIS_ERROR_SEND, + /* types */ + WHEREIS_LOOKUP_PID, /* enif_whereis_pid() */ + WHEREIS_LOOKUP_PORT /* enif_whereis_port() */ +}; + +typedef union { + ErlNifPid pid; + ErlNifPort port; +} whereis_term_data_t; + +/* single use, no cross-thread access/serialization */ +typedef struct { + ErlNifEnv* env; + ERL_NIF_TERM name; + whereis_term_data_t res; + ErlNifTid tid; + int type; +} whereis_thread_resource_t; + +static whereis_thread_resource_t* whereis_thread_resource_create(void) +{ + whereis_thread_resource_t* rp = (whereis_thread_resource_t*) + enif_alloc_resource(whereis_resource_type, sizeof(*rp)); + memset(rp, 0, sizeof(*rp)); + rp->env = enif_alloc_env(); + + return rp; +} + +static void whereis_thread_resource_dtor(ErlNifEnv* env, void* obj) +{ + whereis_thread_resource_t* rp = (whereis_thread_resource_t*) obj; + enif_free_env(rp->env); +} + +static int whereis_type(ERL_NIF_TERM type) +{ + if (enif_is_identical(type, atom_pid)) + return WHEREIS_LOOKUP_PID; + + if (enif_is_identical(type, atom_port)) + return WHEREIS_LOOKUP_PORT; + + return WHEREIS_ERROR_TYPE; +} + +static int whereis_lookup_internal( + ErlNifEnv* env, int type, ERL_NIF_TERM name, whereis_term_data_t* out) +{ + if (type == WHEREIS_LOOKUP_PID) + return enif_whereis_pid(env, name, & out->pid) + ? WHEREIS_SUCCESS : WHEREIS_ERROR_LOOKUP; + + if (type == WHEREIS_LOOKUP_PORT) + return enif_whereis_port(env, name, & out->port) + ? WHEREIS_SUCCESS : WHEREIS_ERROR_LOOKUP; + + return WHEREIS_ERROR_TYPE; +} + +static int whereis_send_internal( + ErlNifEnv* env, int type, whereis_term_data_t* to, ERL_NIF_TERM msg) +{ + if (type == WHEREIS_LOOKUP_PID) + return enif_send(env, & to->pid, NULL, msg) + ? WHEREIS_SUCCESS : WHEREIS_ERROR_SEND; + + if (type == WHEREIS_LOOKUP_PORT) + return enif_port_command(env, & to->port, NULL, msg) + ? WHEREIS_SUCCESS : WHEREIS_ERROR_SEND; + + return WHEREIS_ERROR_TYPE; +} + +static int whereis_resolved_term( + ErlNifEnv* env, int type, whereis_term_data_t* res, ERL_NIF_TERM* out) +{ + switch (type) { + case WHEREIS_LOOKUP_PID: + *out = enif_make_pid(env, & res->pid); + break; + case WHEREIS_LOOKUP_PORT: + *out = enif_make_port(env, & res->port); + break; + default: + return WHEREIS_ERROR_TYPE; + } + return WHEREIS_SUCCESS; +} + +static ERL_NIF_TERM whereis_result_term(ErlNifEnv* env, int result) +{ + ERL_NIF_TERM err; + switch (result) + { + case WHEREIS_SUCCESS: + return atom_ok; + case WHEREIS_ERROR_LOOKUP: + err = atom_lookup; + break; + case WHEREIS_ERROR_SEND: + err = atom_send; + break; + case WHEREIS_ERROR_TYPE: + err = atom_badarg; + break; + default: + err = enif_make_int(env, -result); + break; + } + return enif_make_tuple2(env, atom_error, err); +} + +static void* whereis_lookup_thread(void* arg) +{ + whereis_thread_resource_t* rp = (whereis_thread_resource_t*) arg; + int rc; + + /* enif_whereis_xxx should work with allocated or null env */ + rc = whereis_lookup_internal( + ((rp->type == WHEREIS_LOOKUP_PID) ? NULL : rp->env), + rp->type, rp->name, & rp->res); + + return (((char*) NULL) + rc); +} + +/* whereis_term(Type, Name) -> pid() | port() | false */ +static ERL_NIF_TERM +whereis_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + whereis_term_data_t res; + ERL_NIF_TERM ret; + int type, rc; + + if (argc != 2) /* allow non-atom name for testing */ + return enif_make_badarg(env); + + if ((type = whereis_type(argv[0])) == WHEREIS_ERROR_TYPE) + return enif_make_badarg(env); + + rc = whereis_lookup_internal(env, type, argv[1], & res); + if (rc == WHEREIS_SUCCESS) { + rc = whereis_resolved_term(env, type, & res, & ret); + } + return (rc == WHEREIS_SUCCESS) ? ret : atom_false; +} + +/* whereis_send(Type, Name, Message) -> ok | {error, Reason} */ +static ERL_NIF_TERM +whereis_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + whereis_term_data_t to; + int type, rc; + + if (argc != 3 || !enif_is_atom(env, argv[1])) + return enif_make_badarg(env); + + if ((type = whereis_type(argv[0])) == WHEREIS_ERROR_TYPE) + return enif_make_badarg(env); + + rc = whereis_lookup_internal(env, type, argv[1], & to); + if (rc == WHEREIS_SUCCESS) + rc = whereis_send_internal(env, type, & to, argv[2]); + + return whereis_result_term(env, rc); +} + +/* whereis_thd_lookup(Type, Name) -> {ok, Resource} | {error, SysErrno} */ +static ERL_NIF_TERM +whereis_thd_lookup(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + whereis_thread_resource_t* rp; + int type, rc; + + if (argc != 2 || !enif_is_atom(env, argv[1])) + return enif_make_badarg(env); + + if ((type = whereis_type(argv[0])) == WHEREIS_ERROR_TYPE) + return enif_make_badarg(env); + + rp = whereis_thread_resource_create(); + rp->type = type; + rp->name = enif_make_copy(rp->env, argv[1]); + + rc = enif_thread_create( + "nif_SUITE:whereis_thd", & rp->tid, whereis_lookup_thread, rp, NULL); + + if (rc == 0) { + return enif_make_tuple2(env, atom_ok, enif_make_resource(env, rp)); + } + else { + enif_release_resource(rp); + return enif_make_tuple2(env, atom_error, enif_make_int(env, rc)); + } +} + +/* whereis_thd_result(Resource) -> {ok, pid() | port()} | {error, ErrNum} */ +static ERL_NIF_TERM +whereis_thd_result(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + whereis_thread_resource_t* rp; + ERL_NIF_TERM ret; + char* thdret; /* so we can keep compilers happy converting to int */ + int rc; + + if (argc != 1 + || !enif_get_resource(env, argv[0], whereis_resource_type, (void**) & rp)) + return enif_make_badarg(env); + + if ((rc = enif_thread_join(rp->tid, (void**) & thdret)) != 0) + return enif_make_tuple2(env, atom_error, enif_make_int(env, rc)); + + rc = (int)(thdret - ((char*) NULL)); + if (rc == WHEREIS_SUCCESS) { + rc = whereis_resolved_term(env, rp->type, & rp->res, & ret); + } + ret = (rc == WHEREIS_SUCCESS) + ? enif_make_tuple2(env, atom_ok, ret) : whereis_result_term(env, rc); + + enif_release_resource(rp); + return ret; +} + #define MAKE_TERM_REUSE_LEN 16 struct make_term_info { @@ -2968,7 +3224,11 @@ static ErlNifFunc nif_funcs[] = {"monitor_process_nif", 4, monitor_process_nif}, {"demonitor_process_nif", 2, demonitor_process_nif}, {"compare_monitors_nif", 2, compare_monitors_nif}, - {"monitor_frenzy_nif", 4, monitor_frenzy_nif} + {"monitor_frenzy_nif", 4, monitor_frenzy_nif}, + {"whereis_send", 3, whereis_send}, + {"whereis_term", 2, whereis_term}, + {"whereis_thd_lookup", 2, whereis_thd_lookup}, + {"whereis_thd_result", 1, whereis_thd_result} }; ERL_NIF_INIT(nif_SUITE,nif_funcs,load,NULL,upgrade,unload) -- cgit v1.2.3 From 8543e7e6e92e0e15843f2ce0ea70513d421cd8ae Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 10 May 2017 20:38:32 +0200 Subject: erts: Test monitor resource destructor from thread which is scheduled on non-smp VM. --- erts/emulator/test/nif_SUITE.erl | 15 ++++++++++++++- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 25 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 1eb58699b2..0ae8e02011 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -629,6 +629,15 @@ monitor_process_a(Config) -> monitor_process_b(Config) -> ensure_lib_loaded(Config), + monitor_process_b_do(false), + case erlang:system_info(threads) of + true -> monitor_process_b_do(true); + false -> ok + end, + ok. + + +monitor_process_b_do(FromThread) -> Pid = spawn_link(fun() -> receive return -> ok @@ -637,7 +646,10 @@ monitor_process_b(Config) -> R_ptr = alloc_monitor_resource_nif(), {0,_} = monitor_process_nif(R_ptr, Pid, true, self()), [R_ptr] = monitored_by(Pid), - ok = release_resource(R_ptr), + case FromThread of + false -> ok = release_resource(R_ptr); + true -> ok = release_resource_from_thread(R_ptr) + end, [] = flush(), {R_ptr, _, 1} = last_resource_dtor_call(), [] = monitored_by(Pid), @@ -2789,6 +2801,7 @@ alloc_resource(_,_) -> ?nif_stub. make_resource(_) -> ?nif_stub. get_resource(_,_) -> ?nif_stub. release_resource(_) -> ?nif_stub. +release_resource_from_thread(_) -> ?nif_stub. last_resource_dtor_call() -> ?nif_stub. make_new_resource(_,_) -> ?nif_stub. check_is(_,_,_,_,_,_,_,_,_,_,_) -> ?nif_stub. diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 3747291e7e..4f0400c960 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -972,6 +972,30 @@ static ERL_NIF_TERM release_resource(ErlNifEnv* env, int argc, const ERL_NIF_TER return enif_make_atom(env,"ok"); } +static void* threaded_release_resource(void* resource) +{ + enif_release_resource(resource); +} + +static ERL_NIF_TERM release_resource_from_thread(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + void* resource; + ErlNifTid tid; + int err; + + if (!get_pointer(env, argv[0], &resource)) { + return enif_make_badarg(env); + } + if (enif_thread_create("nif_SUITE:release_resource_from_thread", &tid, + threaded_release_resource, resource, NULL) != 0) { + return enif_make_badarg(env); + } + err = enif_thread_join(tid, NULL); + assert(err == 0); + return atom_ok; +} + + /* * argv[0] an atom * argv[1] a binary @@ -2903,6 +2927,7 @@ static ErlNifFunc nif_funcs[] = {"make_resource", 1, make_resource}, {"get_resource", 2, get_resource}, {"release_resource", 1, release_resource}, + {"release_resource_from_thread", 1, release_resource_from_thread}, {"last_resource_dtor_call", 0, last_resource_dtor_call}, {"make_new_resource", 2, make_new_resource}, {"check_is", 11, check_is}, -- cgit v1.2.3 From fb943b6efa883991377f475f4e24ce16bf948021 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 17 May 2017 19:21:20 +0200 Subject: erts: Improve message flush in nif_SUITE Pass number of expected messages in order to wait longer for messages (for slow machines) while not wasting test time waiting for nothing. --- erts/emulator/test/nif_SUITE.erl | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 0ae8e02011..f9ee96c9ca 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -488,7 +488,7 @@ select(Config) when is_list(Config) -> %% Wait for read eagain = read_nif(R, 3), 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,null,Ref), - [] = flush(), + [] = flush(0), ok = write_nif(W, <<"hej">>), [{select, R, Ref, ready_input}] = flush(), 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,self(),Ref2), @@ -505,7 +505,7 @@ select(Config) when is_list(Config) -> %% Wait for write Written = write_full(W, $a), 0 = select_nif(W,?ERL_NIF_SELECT_WRITE,W,self(),Ref), - [] = flush(), + [] = flush(0), Written = read_nif(R,byte_size(Written)), [{select, W, Ref, ready_output}] = flush(), @@ -515,7 +515,7 @@ select(Config) when is_list(Config) -> [{fd_resource_stop, W_ptr, _}] = flush(), {1, {W_ptr,_}} = last_fd_stop_call(), true = is_closed_nif(W), - [] = flush(), + [] = flush(0), 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,self(),Ref), [{select, R, Ref, ready_input}] = flush(), eof = read_nif(R,1), @@ -540,7 +540,7 @@ select_2(Config) -> 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,null,Ref1), 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,self(),Ref2), - [] = flush(), + [] = flush(0), ok = write_nif(W, <<"hej">>), [{select, R, Ref2, ready_input}] = flush(), <<"hej">> = read_nif(R, 3), @@ -551,7 +551,7 @@ select_2(Config) -> Papa = self(), spawn_link(fun() -> 0 = select_nif(R,?ERL_NIF_SELECT_READ,R,null,Ref1), - [] = flush(), + [] = flush(0), Papa ! sync, [{select, R, Ref1, ready_input}] = flush(), <<"hej">> = read_nif(R, 3), @@ -560,7 +560,7 @@ select_2(Config) -> sync = receive_any(), ok = write_nif(W, <<"hej">>), done = receive_any(), - [] = flush(), + [] = flush(0), check_stop_ret(select_nif(R,?ERL_NIF_SELECT_STOP,R,null,Ref1)), [{fd_resource_stop, R_ptr, _}] = flush(), @@ -650,7 +650,7 @@ monitor_process_b_do(FromThread) -> false -> ok = release_resource(R_ptr); true -> ok = release_resource_from_thread(R_ptr) end, - [] = flush(), + [] = flush(0), {R_ptr, _, 1} = last_resource_dtor_call(), [] = monitored_by(Pid), Pid ! return, @@ -672,7 +672,7 @@ monitor_process_c(Config) -> exit end), [{Pid, done, R_ptr, Mon1}, - {monitor_resource_down, R_ptr, Pid, Mon2}] = flush(), + {monitor_resource_down, R_ptr, Pid, Mon2}] = flush(2), compare_monitors_nif(Mon1, Mon2), {R_ptr, _, 1} = last_resource_dtor_call(), ok. @@ -720,7 +720,7 @@ demonitor_process(Config) -> 1 = demonitor_process_nif(R_ptr, MonBin2), ok = release_resource(R_ptr), - [] = flush(), + [] = flush(0), {R_ptr, _, 1} = last_resource_dtor_call(), [] = monitored_by(Pid), Pid ! return, @@ -2319,10 +2319,16 @@ receive_any(Timeout) -> after Timeout -> timeout end. flush() -> - flush(10). -flush(Timeout) -> + flush(1). + +flush(0) -> + flush(0, 10); % don't waste too much time waiting for nothing +flush(N) -> + flush(N, 1000). + +flush(N, Timeout) -> receive M -> - [M | flush(Timeout)] + [M | flush(N-1)] after Timeout -> [] end. -- cgit v1.2.3 From d05821528fa012b9eaf01dd79d79f4f34f2e86ef Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 22 May 2017 18:23:45 +0200 Subject: erts: Fix nif_SUITE:monitor_frenzy for threadless --- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 4f0400c960..15d31162ed 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -2561,6 +2561,7 @@ static ERL_NIF_TERM monitor_frenzy_nif(ErlNifEnv* env, int argc, const ERL_NIF_T static unsigned long spawn_cnt = 0; static unsigned long kill_cnt = 0; static unsigned long proc_histogram[FRENZY_PROCS_MAX]; + static int initialized = 0; static const unsigned int primes[] = {7, 13, 17, 19}; @@ -2580,7 +2581,7 @@ static ERL_NIF_TERM monitor_frenzy_nif(ErlNifEnv* env, int argc, const ERL_NIF_T if (enif_is_atom(env, Op)) { if (Op == atom_init) { - if (procs_lock || !enif_get_uint(env, Rnd, &frenzy_rand_bits_max)) + if (initialized || !enif_get_uint(env, Rnd, &frenzy_rand_bits_max)) return enif_make_badarg(env); procs_lock = enif_mutex_create("nif_SUITE:monitor_frenzy.procs"); @@ -2607,6 +2608,7 @@ static ERL_NIF_TERM monitor_frenzy_nif(ErlNifEnv* env, int argc, const ERL_NIF_T spawn_cnt = 1; kill_cnt = 0; + initialized = 1; return enif_make_uint(env, 0); /* SelfPix */ } else if (Op == atom_stats) { @@ -2637,7 +2639,7 @@ static ERL_NIF_TERM monitor_frenzy_nif(ErlNifEnv* env, int argc, const ERL_NIF_T enif_make_ulong(env, res_dtor_cnt))); } - else if (Op == atom_stop && procs_lock) { /* stop all */ + else if (Op == atom_stop && initialized) { /* stop all */ /* Release all resources */ for (rix = 0; rix < FRENZY_RESOURCES_MAX; rix++) { -- cgit v1.2.3 From 3907fdbb277efdfd9e0675569fed92d78fc88d73 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 23 May 2017 17:32:47 +0200 Subject: erts: Reduce runtime for nif_SUITE hash tests and base allowed hash deviation on nr of standard deviations to make it easier to fiddle with the work load. --- erts/emulator/test/nif_SUITE.erl | 42 ++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 17 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index f9ee96c9ca..bcea9e3539 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -2637,9 +2637,9 @@ nif_snprintf(Config) -> nif_internal_hash(Config) -> ensure_lib_loaded(Config), HashValueBitSize = nif_hash_result_bitsize(internal), - Terms = unique([random_term() || _ <- lists:seq(1, 5000)]), + Terms = unique([random_term() || _ <- lists:seq(1, 500)]), HashValues = [hash_nif(internal, Term, 0) || Term <- Terms], - test_bit_distribution_fitness(HashValues, HashValueBitSize, 0.05). + test_bit_distribution_fitness(HashValues, HashValueBitSize). nif_internal_hash_salted(Config) -> ensure_lib_loaded(Config), @@ -2648,7 +2648,7 @@ nif_internal_hash_salted(Config) -> nif_phash2(Config) -> ensure_lib_loaded(Config), HashValueBitSize = nif_hash_result_bitsize(phash2), - Terms = unique([random_term() || _ <- lists:seq(1, 5000)]), + Terms = unique([random_term() || _ <- lists:seq(1, 500)]), HashValues = lists:map( fun (Term) -> @@ -2661,12 +2661,12 @@ nif_phash2(Config) -> HashValue end, Terms), - test_bit_distribution_fitness(HashValues, HashValueBitSize, 0.05). + test_bit_distribution_fitness(HashValues, HashValueBitSize). test_salted_nif_hash(HashType) -> HashValueBitSize = nif_hash_result_bitsize(HashType), - Terms = unique([random_term() || _ <- lists:seq(1, 5000)]), - Salts = unique([random_uint32() || _ <- lists:seq(1, 100)]), + Terms = unique([random_term() || _ <- lists:seq(1, 500)]), + Salts = unique([random_uint32() || _ <- lists:seq(1, 50)]), {HashValuesPerSalt, HashValuesPerTerm} = lists:mapfoldl( fun (Salt, Acc) -> @@ -2687,22 +2687,20 @@ test_salted_nif_hash(HashType) -> % Test per-salt hash distribution of different terms lists:foreach( fun ({_Salt, HashValues}) -> - test_bit_distribution_fitness(HashValues, HashValueBitSize, 0.05) + test_bit_distribution_fitness(HashValues, HashValueBitSize) end, HashValuesPerSalt), % Test per-term hash distribution of different salts dict:fold( fun (_Term, HashValues, Acc) -> - % Be more tolerant of relative deviation, - % as there's fewer hash values here. - test_bit_distribution_fitness(HashValues, HashValueBitSize, 0.30), + test_bit_distribution_fitness(HashValues, HashValueBitSize), Acc end, ok, HashValuesPerTerm). -test_bit_distribution_fitness(Integers, BitSize, MaxRelativeDeviation) -> +test_bit_distribution_fitness(Integers, BitSize) -> MaxInteger = (1 bsl BitSize) - 1, OnesPerBit = lists:foldl( @@ -2718,19 +2716,29 @@ test_bit_distribution_fitness(Integers, BitSize, MaxRelativeDeviation) -> orddict:new(), Integers), - ExpectedNrOfOnes = length(Integers) div 2, + N = length(Integers), + ExpectedNrOfOnes = N div 2, + %% ExpectedNrOfOnes should have a binomial distribution + %% with a standard deviation as: + ExpectedStdDev = math:sqrt(N) / 2, + %% which can be approximated as a normal distribution + %% where we allow a deviation of 6 std.devs + %% for a fail probability of 0.000000002: + MaxStdDevs = 6, + FailureText = orddict:fold( fun (BitIndex, NrOfOnes, Acc) -> - RelativeDeviation = abs(NrOfOnes - ExpectedNrOfOnes) / length(Integers), - case RelativeDeviation >= MaxRelativeDeviation of - false -> Acc; + Deviation = abs(NrOfOnes - ExpectedNrOfOnes) / ExpectedStdDev, + case Deviation >= MaxStdDevs of + false -> + Acc; true -> [Acc, io_lib:format( "Unreasonable deviation on number of set bits (i=~p): " - "expected ~p, got ~p (relative dev. ~.3f)~n", - [BitIndex, ExpectedNrOfOnes, NrOfOnes, RelativeDeviation])] + "expected ~p, got ~p (# std.dev ~.3f > ~p)~n", + [BitIndex, ExpectedNrOfOnes, NrOfOnes, Deviation, MaxStdDevs])] end end, [], -- cgit v1.2.3 From 666de16fbea2e06b76e1850296ee42eda563a4c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 24 May 2017 14:42:39 +0200 Subject: bs_construct_SUITE: Correct calculation of free memory free_mem/0 returned the number of free Kb, but the caller assumed that it was in Mb. Also add another clause to further scale down the size of the binaries created. --- erts/emulator/test/bs_construct_SUITE.erl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/bs_construct_SUITE.erl b/erts/emulator/test/bs_construct_SUITE.erl index 95042ac802..ed03284a5b 100644 --- a/erts/emulator/test/bs_construct_SUITE.erl +++ b/erts/emulator/test/bs_construct_SUITE.erl @@ -537,6 +537,8 @@ huge_binary(Config) when is_list(Config) -> ct:timetrap({seconds, 60}), 16777216 = size(<<0:(id(1 bsl 26)),(-1):(id(1 bsl 26))>>), garbage_collect(), + FreeMem = free_mem(), + io:format("Free memory (Mb): ~p\n", [FreeMem]), {Shift,Return} = case free_mem() of undefined -> %% This test has to be inlined inside the case to @@ -552,10 +554,14 @@ huge_binary(Config) when is_list(Config) -> garbage_collect(), id(<<0:((1 bsl 31)-1)>>), {31,"Limit huge binaries to 256 Mb"}; - _ -> + Mb when Mb > 200 -> garbage_collect(), id(<<0:((1 bsl 30)-1)>>), - {30,"Limit huge binary to 128 Mb"} + {30,"Limit huge binary to 128 Mb"}; + _ -> + garbage_collect(), + id(<<0:((1 bsl 29)-1)>>), + {29,"Limit huge binary to 64 Mb"} end, garbage_collect(), id(<<0:((1 bsl Shift)-1)>>), @@ -567,13 +573,14 @@ huge_binary(Config) when is_list(Config) -> Comment -> {comment, Comment} end. +%% Return the amount of free memory in Mb. free_mem() -> {ok,Apps} = application:ensure_all_started(os_mon), Mem = memsup:get_system_memory_data(), [ok = application:stop(App)||App <- Apps], case proplists:get_value(free_memory,Mem) of undefined -> undefined; - Val -> Val div 1024 + Val -> Val div (1024*1024) end. system_limit(Config) when is_list(Config) -> -- cgit v1.2.3 From 0ddedf0680ae23ead8ebf7999af846ce5d722d36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Wed, 24 May 2017 15:32:31 +0200 Subject: Fix a race condition that consistently affected lc+lcnt builds The garbage_collect message could be received while waiting for trace messages, causing the test to crash erroneously. --- erts/emulator/test/gc_SUITE.erl | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/gc_SUITE.erl b/erts/emulator/test/gc_SUITE.erl index 35dd147550..02b1927621 100644 --- a/erts/emulator/test/gc_SUITE.erl +++ b/erts/emulator/test/gc_SUITE.erl @@ -268,24 +268,30 @@ minor_major_gc_option_async(_Config) -> erlang:trace(P4, true, [garbage_collection]), ?assertEqual(async, erlang:garbage_collect(P4, [{type, minor}, {async, Ref}])), + receive + {garbage_collect, Ref, true} -> + ok + after 10000 -> + ct:pal("Did not receive an async GC notification", []), + ?assert(false) + end, expect_trace_messages(P4, [gc_minor_start, gc_minor_end]), erlang:trace(P4, false, [garbage_collection]), - receive {garbage_collect, Ref, true} -> ok; - Other4 -> ct:pal("Unexpected message: ~p~n" - ++ "while waiting for async gc result", [Other4]) - after 2000 -> ?assert(false) - end, erlang:exit(P4, kill). -%% Given a list of atoms, trace tags - receives messages and checks if they are -%% trace events, and if the tag matches. Else will crash failing the test. -expect_trace_messages(_Pid, []) -> ok; -expect_trace_messages(Pid, [Tag | TraceTags]) -> +%% Ensures that trace messages with the provided tags have all been received. +%% The test fails if there's any unmatched messages left in the mailbox after +%% all tags have been matched. +expect_trace_messages(_Pid, []) -> receive - {trace, Pid, Tag, _Data} -> ok; - AnythingElse -> - ct:pal("Unexpected message: ~p~nWhile expected {trace, _, ~p, _}", - [AnythingElse, Tag]), + Anything -> + ct:pal("Unexpected message: ~p", [Anything]), ?assert(false) + after 0 -> + ok + end; +expect_trace_messages(Pid, [Tag | TraceTags]) -> + receive + {trace, Pid, Tag, _Data} -> ok end, expect_trace_messages(Pid, TraceTags). -- cgit v1.2.3 From acd8571b35756c3fdc389807c34d80c9d44435e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 31 May 2017 12:55:40 +0200 Subject: Make sure that asynchronous replies are not lost (First attempt to fix in 23f132d9ab776a.) If an synchronous GC was requested by calling: erlang:garbage_collect(Pid, [{async,Ref}]) the reply message could in certain circumstances be lost. The problem is that cleanup_sys_tasks() is never called if there are dirty tasks, but no other active system tasks. Also shorten the long waiting times in the test case binary_SUITE:trapping/1 to make it much more likely that the GC have not already finished when the process is killed. --- erts/emulator/test/binary_SUITE.erl | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl index 355be7a36d..4d17276e5c 100644 --- a/erts/emulator/test/binary_SUITE.erl +++ b/erts/emulator/test/binary_SUITE.erl @@ -1358,17 +1358,19 @@ do_trapping(N, Bif, ArgFun) -> io:format("N=~p: Do ~p ~s gc.\n", [N, Bif, case N rem 2 of 0 -> "with"; 1 -> "without" end]), Pid = spawn(?MODULE,trapping_loop,[Bif, ArgFun, 1000, self()]), receive ok -> ok end, - receive after 100 -> ok end, Ref = make_ref(), case N rem 2 of - 0 -> erlang:garbage_collect(Pid, [{async,Ref}]), - receive after 100 -> ok end; + 0 -> + erlang:garbage_collect(Pid, [{async,Ref}]), + receive after 1 -> ok end; 1 -> void end, - exit(Pid,kill), + exit(Pid, kill), case N rem 2 of - 0 -> receive {garbage_collect, Ref, _} -> ok end; - 1 -> void + 0 -> + receive {garbage_collect, Ref, _} -> ok end; + 1 -> + void end, receive after 1 -> ok end, do_trapping(N-1, Bif, ArgFun). -- cgit v1.2.3 From e86537cf39a6abe5b68bd418f3cc92b03c68b40f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Wed, 31 May 2017 12:40:19 +0200 Subject: Break out a lot of duplicated code in minor_major_gc_option_ZZZ --- erts/emulator/test/gc_SUITE.erl | 151 +++++++++++++++++++--------------------- 1 file changed, 73 insertions(+), 78 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/gc_SUITE.erl b/erts/emulator/test/gc_SUITE.erl index 02b1927621..2c2cb9c32d 100644 --- a/erts/emulator/test/gc_SUITE.erl +++ b/erts/emulator/test/gc_SUITE.erl @@ -203,95 +203,90 @@ long_receive() -> end. minor_major_gc_option_self(_Config) -> - Endless = fun Endless() -> - receive - {gc, Type} -> erlang:garbage_collect(self(), [{type, Type}]) - after 100 -> ok end, - Endless() - end, - - %% Try as major, a test process will self-trigger GC - P1 = spawn(Endless), - erlang:garbage_collect(P1, []), - erlang:trace(P1, true, [garbage_collection]), - P1 ! {gc, major}, - expect_trace_messages(P1, [gc_major_start, gc_major_end]), - erlang:trace(P1, false, [garbage_collection]), - erlang:exit(P1, kill), - - %% Try as minor, a test process will self-trigger GC - P2 = spawn(Endless), - erlang:garbage_collect(P2, []), - erlang:trace(P2, true, [garbage_collection]), - P2 ! {gc, minor}, - expect_trace_messages(P2, [gc_minor_start, gc_minor_end]), - erlang:trace(P2, false, [garbage_collection]), - erlang:exit(P2, kill). + %% Try as major, the test process will self-trigger GC + check_gc_tracing_around( + fun(Pid, Ref) -> + Pid ! {gc, Ref, major} + end, [gc_major_start, gc_major_end]), + + %% Try as minor, the test process will self-trigger GC + check_gc_tracing_around( + fun(Pid, Ref) -> + Pid ! {gc, Ref, minor} + end, [gc_minor_start, gc_minor_end]). minor_major_gc_option_async(_Config) -> - Endless = fun Endless() -> - receive after 100 -> ok end, - Endless() - end, - - %% Try with default option, must be major gc - P1 = spawn(Endless), - erlang:garbage_collect(P1, []), - erlang:trace(P1, true, [garbage_collection]), - erlang:garbage_collect(P1, []), - expect_trace_messages(P1, [gc_major_start, gc_major_end]), - erlang:trace(P1, false, [garbage_collection]), - erlang:exit(P1, kill), + %% Try with default option, must be major GC + check_gc_tracing_around( + fun(Pid, _Ref) -> + erlang:garbage_collect(Pid, []) + end, [gc_major_start, gc_major_end]), %% Try with the 'major' type - P2 = spawn(Endless), - erlang:garbage_collect(P2, []), - erlang:trace(P2, true, [garbage_collection]), - erlang:garbage_collect(P2, [{type, major}]), - expect_trace_messages(P2, [gc_major_start, gc_major_end]), - erlang:trace(P2, false, [garbage_collection]), - erlang:exit(P2, kill), + check_gc_tracing_around( + fun(Pid, _Ref) -> + erlang:garbage_collect(Pid, [{type, major}]) + end, [gc_major_start, gc_major_end]), %% Try with 'minor' option, once - P3 = spawn(Endless), - erlang:garbage_collect(P3, []), - erlang:trace(P3, true, [garbage_collection]), - erlang:garbage_collect(P3, [{type, minor}]), - expect_trace_messages(P3, [gc_minor_start, gc_minor_end]), - erlang:trace(P3, false, [garbage_collection]), - erlang:exit(P3, kill), + check_gc_tracing_around( + fun(Pid, _Ref) -> + erlang:garbage_collect(Pid, [{type, minor}]) + end, [gc_minor_start, gc_minor_end]), %% Try with 'minor' option, once, async - P4 = spawn(Endless), + check_gc_tracing_around( + fun(Pid, Ref) -> + ?assertEqual(async, + erlang:garbage_collect(Pid, [{type, minor}, {async, Ref}])), + + receive + {garbage_collect, Ref, true} -> + ok + after 10000 -> + ct:fail("Did not receive a completion notification on async GC") + end + end, [gc_minor_start, gc_minor_end]). + +%% Traces garbage collection around the given operation, and fails the test if +%% it results in any unexpected messages or if the expected trace tags are not +%% received. +check_gc_tracing_around(Fun, ExpectedTraceTags) -> Ref = erlang:make_ref(), - erlang:garbage_collect(P4, []), - erlang:trace(P4, true, [garbage_collection]), - ?assertEqual(async, - erlang:garbage_collect(P4, [{type, minor}, {async, Ref}])), - receive - {garbage_collect, Ref, true} -> - ok - after 10000 -> - ct:pal("Did not receive an async GC notification", []), - ?assert(false) - end, - expect_trace_messages(P4, [gc_minor_start, gc_minor_end]), - erlang:trace(P4, false, [garbage_collection]), - erlang:exit(P4, kill). - -%% Ensures that trace messages with the provided tags have all been received. -%% The test fails if there's any unmatched messages left in the mailbox after -%% all tags have been matched. + Pid = spawn( + fun Endless() -> + receive + {gc, Ref, Type} -> + erlang:garbage_collect(self(), [{type, Type}]) + after 100 -> + ok + end, + Endless() + end), + erlang:garbage_collect(Pid, []), + erlang:trace(Pid, true, [garbage_collection]), + Fun(Pid, Ref), + expect_trace_messages(Pid, ExpectedTraceTags), + erlang:trace(Pid, false, [garbage_collection]), + erlang:exit(Pid, kill), + check_no_unexpected_messages(). + +%% Ensures that trace messages with the provided tags have all been received +%% within a reasonable timeframe. expect_trace_messages(_Pid, []) -> + ok; +expect_trace_messages(Pid, [Tag | TraceTags]) -> + receive + {trace, Pid, Tag, _Data} -> + expect_trace_messages(Pid, TraceTags) + after 4000 -> + ct:fail("Didn't receive tag ~p within 4000ms", [Tag]) + end. + +check_no_unexpected_messages() -> receive Anything -> - ct:pal("Unexpected message: ~p", [Anything]), - ?assert(false) + ct:fail("Unexpected message: ~p", [Anything]) after 0 -> ok - end; -expect_trace_messages(Pid, [Tag | TraceTags]) -> - receive - {trace, Pid, Tag, _Data} -> ok - end, - expect_trace_messages(Pid, TraceTags). + end. -- cgit v1.2.3 From de2685850a498a3d968622fd9ab23b8aca2047c7 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Thu, 1 Jun 2017 21:09:24 +0200 Subject: Update testcase to check that purge handle hibernated process correct --- erts/emulator/test/code_SUITE.erl | 40 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index 9f318a38be..fcb6485e7e 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -492,7 +492,38 @@ constant_pools(Config) when is_list(Config) -> receive {'EXIT',OldHeap,{A,B,C,[1,2,3|_]=Seq}} when length(Seq) =:= 16 -> ok - end. + end, + + {module,literals} = erlang:load_module(literals, Code), + %% Have a hibernated process that references the literals + %% in the 'literals' module. + {Hib, Mon} = spawn_monitor(fun() -> hibernated(Self) end), + receive go -> ok end, + [{heap_size,OldHeapSz}, + {total_heap_size,OldTotHeapSz}] = process_info(Hib, [heap_size, + total_heap_size]), + OldHeapSz = OldTotHeapSz, + io:format("OldHeapSz=~p OldTotHeapSz=~p~n", [OldHeapSz, OldTotHeapSz]), + true = erlang:delete_module(literals), + false = erlang:check_process_code(Hib, literals), + erlang:check_process_code(self(), literals), + erlang:purge_module(literals), + receive after 1000 -> ok end, + [{heap_size,HeapSz}, + {total_heap_size,TotHeapSz}] = process_info(Hib, [heap_size, + total_heap_size]), + io:format("HeapSz=~p TotHeapSz=~p~n", [HeapSz, TotHeapSz]), + Hib ! hej, + receive + {'DOWN', Mon, process, Hib, Reason} -> + {undef, [{no_module, + no_function, + [{A,B,C,[1,2,3|_]=Seq}], _}]} = Reason, + 16 = length(Seq) + end, + HeapSz = TotHeapSz, %% Ensure restored to hibernated state... + true = HeapSz > OldHeapSz, + ok. no_old_heap(Parent) -> A = literals:a(), @@ -515,6 +546,13 @@ old_heap(Parent) -> exit(Res) end. +hibernated(Parent) -> + A = literals:a(), + B = literals:b(), + Res = {A,B,literals:huge_bignum(),lists:seq(1, 16)}, + Parent ! go, + erlang:hibernate(no_module, no_function, [Res]). + create_old_heap() -> case process_info(self(), [heap_size,total_heap_size]) of [{heap_size,Sz},{total_heap_size,Total}] when Sz < Total -> -- cgit v1.2.3 From 8f87dd1eaa80bdad501ad6f7767f14b4e0cb01d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 30 May 2017 09:40:43 +0200 Subject: Fix process_SUITE:low_prio/1 It is expected that low-priority processes should be allowed to run about 1/8 of the time of normal-priority processes. The proportion calculated was usually considerably lower than 1/8. It seems that the main reason is the punishement in reductions when sending to a process that alreday has many messages in the message queue. I have verified that by running the emulator with the +snsp to turn off the send punishment. To avoid that punishment, let the server process run at high priority so that it can keep its message queue short. It seems that the proportion is now very close to 1/8. Therefore, we can tighten the margins for the proportion. --- erts/emulator/test/process_SUITE.erl | 50 ++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 19 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index e14185e881..a65c3f0cad 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -1024,36 +1024,48 @@ bump_big(Prev, Limit) -> %% Priority 'low' should be mixed with 'normal' using a factor of %% about 8. (OTP-2644) low_prio(Config) when is_list(Config) -> - case erlang:system_info(schedulers_online) of - 1 -> - ok = low_prio_test(Config); - _ -> - erlang:system_flag(multi_scheduling, block_normal), - ok = low_prio_test(Config), - erlang:system_flag(multi_scheduling, unblock_normal), - {comment, - "Test not written for SMP runtime system. " - "Multi scheduling blocked during test."} - end. + erlang:system_flag(multi_scheduling, block_normal), + Prop = low_prio_test(Config), + erlang:system_flag(multi_scheduling, unblock_normal), + Str = lists:flatten(io_lib:format("Low/high proportion is ~.3f", + [Prop])), + {comment,Str}. low_prio_test(Config) when is_list(Config) -> process_flag(trap_exit, true), - S = spawn_link(?MODULE, prio_server, [0, 0]), + + %% Spawn the server running with high priority. The server must + %% not run at normal priority as that would skew the results for + %% two reasons: + %% + %% 1. There would be one more normal-priority processes than + %% low-priority processes. + %% + %% 2. The receive queue would grow faster than the server process + %% could process it. That would in turn trigger the reduction + %% punishment for the clients. + S = spawn_opt(?MODULE, prio_server, [0, 0], [link,{priority,high}]), + + %% Spawn the clients and let them run for a while. PCs = spawn_prio_clients(S, erlang:system_info(schedulers_online)), - ct:sleep({seconds,3}), + ct:sleep({seconds,2}), lists:foreach(fun (P) -> exit(P, kill) end, PCs), + + %% Stop the server and retrieve the result. S ! exit, - receive {'EXIT', S, {A, B}} -> check_prio(A, B) end, - ok. + receive + {'EXIT', S, {A, B}} -> + check_prio(A, B) + end. check_prio(A, B) -> Prop = A/B, ok = io:format("Low=~p, High=~p, Prop=~p\n", [A, B, Prop]), - %% It isn't 1/8, it's more like 0.3, but let's check that - %% the low-prio processes get some little chance to run at all. - true = (Prop < 1.0), - true = (Prop > 1/32). + %% Prop is expected to be appr. 1/8. Allow a reasonable margin. + true = Prop < 1/4, + true = Prop > 1/16, + Prop. prio_server(A, B) -> receive -- cgit v1.2.3 From 8381b753ce94769691a6dc499f4d40373cb0504c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 30 May 2017 14:05:35 +0200 Subject: Lengthen too short timetraps c062dfc485a added timetraps to test suites that had no timetraps. Some of added timetraps are only 5 or 10 seconds, which is can be too short time on some slow computers. Change those times to one or two minutes. --- erts/emulator/test/bs_construct_SUITE.erl | 2 +- erts/emulator/test/call_trace_SUITE.erl | 2 +- erts/emulator/test/ddll_SUITE.erl | 2 +- erts/emulator/test/evil_SUITE.erl | 2 +- erts/emulator/test/exception_SUITE.erl | 2 +- erts/emulator/test/lttng_SUITE.erl | 2 +- erts/emulator/test/match_spec_SUITE.erl | 2 +- erts/emulator/test/nested_SUITE.erl | 2 +- erts/emulator/test/port_SUITE.erl | 2 +- erts/emulator/test/port_trace_SUITE.erl | 2 +- erts/emulator/test/trace_SUITE.erl | 2 +- erts/emulator/test/trace_port_SUITE.erl | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/bs_construct_SUITE.erl b/erts/emulator/test/bs_construct_SUITE.erl index ed03284a5b..779d81daa5 100644 --- a/erts/emulator/test/bs_construct_SUITE.erl +++ b/erts/emulator/test/bs_construct_SUITE.erl @@ -35,7 +35,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 10}}]. + {timetrap, {minutes, 1}}]. all() -> [test1, test2, test3, test4, test5, testf, not_used, diff --git a/erts/emulator/test/call_trace_SUITE.erl b/erts/emulator/test/call_trace_SUITE.erl index 95171d04ce..1251d644ae 100644 --- a/erts/emulator/test/call_trace_SUITE.erl +++ b/erts/emulator/test/call_trace_SUITE.erl @@ -43,7 +43,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 30}}]. + {timetrap, {minutes, 2}}]. all() -> Common = [errors, on_load], diff --git a/erts/emulator/test/ddll_SUITE.erl b/erts/emulator/test/ddll_SUITE.erl index 0b9f76a892..031b05790d 100644 --- a/erts/emulator/test/ddll_SUITE.erl +++ b/erts/emulator/test/ddll_SUITE.erl @@ -55,7 +55,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 10}}]. + {timetrap, {minutes, 1}}]. all() -> [ddll_test, errors, reference_count, kill_port, diff --git a/erts/emulator/test/evil_SUITE.erl b/erts/emulator/test/evil_SUITE.erl index 9416ac7a02..fb1954ce37 100644 --- a/erts/emulator/test/evil_SUITE.erl +++ b/erts/emulator/test/evil_SUITE.erl @@ -34,7 +34,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 30}}]. + {timetrap, {minutes, 1}}]. all() -> [heap_frag, encode_decode_ext, decode_integer_ext, diff --git a/erts/emulator/test/exception_SUITE.erl b/erts/emulator/test/exception_SUITE.erl index 76e3556bc4..ad6d8c890f 100644 --- a/erts/emulator/test/exception_SUITE.erl +++ b/erts/emulator/test/exception_SUITE.erl @@ -33,7 +33,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 10}}]. + {timetrap, {minutes, 1}}]. all() -> [badmatch, pending_errors, nil_arith, stacktrace, diff --git a/erts/emulator/test/lttng_SUITE.erl b/erts/emulator/test/lttng_SUITE.erl index c12f63706a..1c1952f912 100644 --- a/erts/emulator/test/lttng_SUITE.erl +++ b/erts/emulator/test/lttng_SUITE.erl @@ -40,7 +40,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 10}}]. + {timetrap, {minutes, 1}}]. all() -> [t_lttng_list, diff --git a/erts/emulator/test/match_spec_SUITE.erl b/erts/emulator/test/match_spec_SUITE.erl index eb189c2c33..92ddc23592 100644 --- a/erts/emulator/test/match_spec_SUITE.erl +++ b/erts/emulator/test/match_spec_SUITE.erl @@ -42,7 +42,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 30}}]. + {timetrap, {minutes, 1}}]. all() -> case test_server:is_native(match_spec_SUITE) of diff --git a/erts/emulator/test/nested_SUITE.erl b/erts/emulator/test/nested_SUITE.erl index 7af2873ce2..5059317172 100644 --- a/erts/emulator/test/nested_SUITE.erl +++ b/erts/emulator/test/nested_SUITE.erl @@ -27,7 +27,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 10}}]. + {timetrap, {minutes, 1}}]. all() -> [case_in_case, case_in_after, catch_in_catch, diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index 94ee9851dd..fccbaf13ee 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -153,7 +153,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 10}}]. + {timetrap, {minutes, 1}}]. all() -> [otp_6224, {group, stream}, basic_ping, slow_writes, diff --git a/erts/emulator/test/port_trace_SUITE.erl b/erts/emulator/test/port_trace_SUITE.erl index 03efdc15db..bfc3c8cb51 100644 --- a/erts/emulator/test/port_trace_SUITE.erl +++ b/erts/emulator/test/port_trace_SUITE.erl @@ -52,7 +52,7 @@ -define(ECHO_DRV_REMOTE_SEND_TERM, 15). suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 30}}]. + {timetrap, {minutes, 2}}]. all() -> [port_specs, ports, open_close, diff --git a/erts/emulator/test/trace_SUITE.erl b/erts/emulator/test/trace_SUITE.erl index 643c2e0472..53249229c9 100644 --- a/erts/emulator/test/trace_SUITE.erl +++ b/erts/emulator/test/trace_SUITE.erl @@ -46,7 +46,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 5}}]. + {timetrap, {minutes, 1}}]. all() -> [cpu_timestamp, receive_trace, link_receive_call_correlation, diff --git a/erts/emulator/test/trace_port_SUITE.erl b/erts/emulator/test/trace_port_SUITE.erl index e4db368ea1..5eb27a7b68 100644 --- a/erts/emulator/test/trace_port_SUITE.erl +++ b/erts/emulator/test/trace_port_SUITE.erl @@ -37,7 +37,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 30}}]. + {timetrap, {minutes, 2}}]. all() -> [call_trace, return_trace, send, receive_trace, -- cgit v1.2.3 From 98fde55efd0f8c3f5013329cf3d1acfe7516ab38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 30 May 2017 14:25:34 +0200 Subject: receive_SUITE: Remove ?line macros --- erts/emulator/test/trace_SUITE.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/trace_SUITE.erl b/erts/emulator/test/trace_SUITE.erl index 53249229c9..bd0ea22de9 100644 --- a/erts/emulator/test/trace_SUITE.erl +++ b/erts/emulator/test/trace_SUITE.erl @@ -184,10 +184,10 @@ receive_trace(Config) when is_list(Config) -> {'EXIT', Intruder, {badarg, _}} = receive_first(), %% Untrace the process; we should not receive anything. - ?line 1 = erlang:trace(Receiver, false, ['receive']), - ?line Receiver ! {hello, there}, - ?line Receiver ! any_garbage, - ?line receive_nothing(), + 1 = erlang:trace(Receiver, false, ['receive']), + Receiver ! {hello, there}, + Receiver ! any_garbage, + receive_nothing(), %% Verify restrictions in matchspec for 'receive' F3 = fun (Pat) -> {'EXIT', {badarg,_}} = (catch erlang:trace_pattern('receive', Pat, [])) end, -- cgit v1.2.3 From f5c6195f7cfaea66ab3137ba5fa30f90626c8213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 30 May 2017 16:14:32 +0200 Subject: distribution_SUITE: Refactor bulk_send_bigbig/1 Refactor bulk_send_bigbig/1 to make it somewhat easier to follow. --- erts/emulator/test/distribution_SUITE.erl | 122 +++++++++++++++--------------- 1 file changed, 59 insertions(+), 63 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl index 434e729310..78d67ef2ae 100644 --- a/erts/emulator/test/distribution_SUITE.erl +++ b/erts/emulator/test/distribution_SUITE.erl @@ -62,8 +62,7 @@ -export([sender/3, receiver2/2, dummy_waiter/0, dead_process/0, roundtrip/1, bounce/1, do_dist_auto_connect/1, inet_rpc_server/1, dist_parallel_sender/3, dist_parallel_receiver/0, - dist_evil_parallel_receiver/0, - sendersender/4, sendersender2/4]). + dist_evil_parallel_receiver/0]). %% epmd_module exports -export([start_link/0, register_node/2, register_node/3, port_please/2]). @@ -129,33 +128,43 @@ bulk_send_small(Config) when is_list(Config) -> bulk_send_big(Config) when is_list(Config) -> bulk_send(32, 64). -bulk_send_bigbig(Config) when is_list(Config) -> - bulk_sendsend(32*5, 4). - bulk_send(Terms, BinSize) -> ct:timetrap({seconds, 30}), io:format("Sending ~w binaries, each of size ~w K", [Terms, BinSize]), {ok, Node} = start_node(bulk_receiver), Recv = spawn(Node, erlang, apply, [fun receiver/2, [0, 0]]), - Bin = list_to_binary(lists:duplicate(BinSize*1024, 253)), + Bin = binary:copy(<<253>>, BinSize*1024), Size = Terms*size(Bin), {Elapsed, {Terms, Size}} = test_server:timecall(?MODULE, sender, [Recv, Bin, Terms]), stop_node(Node), - {comment, integer_to_list(trunc(Size/1024/max(1,Elapsed)+0.5)) ++ " K/s"}. + {comment, integer_to_list(round(Size/1024/max(1,Elapsed))) ++ " K/s"}. + +sender(To, _Bin, 0) -> + To ! {done, self()}, + receive + Any -> + Any + end; +sender(To, Bin, Left) -> + To ! {term, Bin}, + sender(To, Bin, Left-1). -bulk_sendsend(Terms, BinSize) -> +bulk_send_bigbig(Config) when is_list(Config) -> + Terms = 32*5, + BinSize = 4, {Rate1, MonitorCount1} = bulk_sendsend2(Terms, BinSize, 5), {Rate2, MonitorCount2} = bulk_sendsend2(Terms, BinSize, 995), Ratio = if MonitorCount2 == 0 -> MonitorCount1 / 1.0; true -> MonitorCount1 / MonitorCount2 end, - Comment = integer_to_list(Rate1) ++ " K/s, " ++ - integer_to_list(Rate2) ++ " K/s, " ++ - integer_to_list(MonitorCount1) ++ " monitor msgs, " ++ - integer_to_list(MonitorCount2) ++ " monitor msgs, " ++ - float_to_list(Ratio) ++ " monitor ratio", + Comment0 = io_lib:format("~p K/s, ~p K/s, " + "~p monitor msgs, ~p monitor msgs, " + "~.1f monitor ratio", + [Rate1,Rate2,MonitorCount1, + MonitorCount2,Ratio]), + Comment = lists:flatten(Comment0), if %% A somewhat arbitrary ratio, but hopefully one that will %% accommodate a wide range of CPU speeds. @@ -169,12 +178,11 @@ bulk_sendsend(Terms, BinSize) -> bulk_sendsend2(Terms, BinSize, BusyBufSize) -> ct:timetrap({seconds, 30}), - io:format("Sending ~w binaries, each of size ~w K", + io:format("\nSending ~w binaries, each of size ~w K", [Terms, BinSize]), {ok, NodeRecv} = start_node(bulk_receiver), Recv = spawn(NodeRecv, erlang, apply, [fun receiver/2, [0, 0]]), - Bin = list_to_binary(lists:duplicate(BinSize*1024, 253)), - %%Size = Terms*size(Bin), + Bin = binary:copy(<<253>>, BinSize*1024), %% SLF LEFT OFF HERE. %% When the caller uses small hunks, like 4k via @@ -185,74 +193,62 @@ bulk_sendsend2(Terms, BinSize, BusyBufSize) -> %% default busy size and "+zdbbl 5", and if the 5 case gets %% "many many more" monitor messages, then we know we're working. - {ok, NodeSend} = start_node(bulk_sender, "+zdbbl " ++ integer_to_list(BusyBufSize)), - _Send = spawn(NodeSend, erlang, apply, [fun sendersender/4, [self(), Recv, Bin, Terms]]), + {ok, NodeSend} = start_node(bulk_sender, "+zdbbl " ++ + integer_to_list(BusyBufSize)), + _Send = spawn(NodeSend, erlang, apply, + [fun sendersender/4, [self(), Recv, Bin, Terms]]), {Elapsed, {_TermsN, SizeN}, MonitorCount} = - receive - %% On some platforms (windows), the time taken is 0 so we - %% simulate that some little time has passed. - {sendersender, {0.0,T,MC}} -> - {0.0015, T, MC}; - {sendersender, BigRes} -> - BigRes - end, + receive + %% On some platforms (Windows), the time taken is 0 so we + %% simulate that some little time has passed. + {sendersender, {0.0,T,MC}} -> + {0.0015, T, MC}; + {sendersender, BigRes} -> + BigRes + end, stop_node(NodeRecv), stop_node(NodeSend), - {trunc(SizeN/1024/Elapsed+0.5), MonitorCount}. - -sender(To, _Bin, 0) -> - To ! {done, self()}, - receive - Any -> - Any - end; -sender(To, Bin, Left) -> - To ! {term, Bin}, - sender(To, Bin, Left-1). + {round(SizeN/1024/Elapsed), MonitorCount}. %% Sender process to be run on a slave node sendersender(Parent, To, Bin, Left) -> erlang:system_monitor(self(), [busy_dist_port]), - [spawn(fun() -> sendersender2(To, Bin, Left, false) end) || - _ <- lists:seq(1,1)], + _ = spawn(fun() -> + sendersender_send(To, Bin, Left), + exit(normal) + end), {USec, {Res, MonitorCount}} = - timer:tc(?MODULE, sendersender2, [To, Bin, Left, true]), + timer:tc(fun() -> + sendersender_send(To, Bin, Left), + To ! {done, self()}, + count_monitors(0) + end), Parent ! {sendersender, {USec/1000000, Res, MonitorCount}}. -sendersender2(To, Bin, Left, SendDone) -> - sendersender3(To, Bin, Left, SendDone, 0). +sendersender_send(_To, _Bin, 0) -> + ok; +sendersender_send(To, Bin, Left) -> + To ! {term, Bin}, + sendersender_send(To, Bin, Left-1). -sendersender3(To, _Bin, 0, SendDone, MonitorCount) -> - if SendDone -> - To ! {done, self()}; - true -> - ok - end, +count_monitors(MonitorCount) -> receive {monitor, _Pid, _Type, _Info} -> - sendersender3(To, _Bin, 0, SendDone, MonitorCount + 1) + count_monitors(MonitorCount + 1) after 0 -> - if SendDone -> - receive - Any when is_tuple(Any), size(Any) == 2 -> - {Any, MonitorCount} - end; - true -> - exit(normal) - end - end; -sendersender3(To, Bin, Left, SendDone, MonitorCount) -> - To ! {term, Bin}, - %%timer:sleep(50), - sendersender3(To, Bin, Left-1, SendDone, MonitorCount). + receive + {_,_}=Any -> + {Any,MonitorCount} + end + end. %% Receiver process to be run on a slave node. receiver(Terms, Size) -> receive {term, Bin} -> - receiver(Terms+1, Size+size(Bin)); + receiver(Terms+1, Size+byte_size(Bin)); {done, ReplyTo} -> ReplyTo ! {Terms, Size} end. -- cgit v1.2.3 From 94e8b18640304bb20dc591a459802ba99dbbd39e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 30 May 2017 16:18:10 +0200 Subject: Make bulk_send_bigbig/1 purely informational bulk_send_bigbig/1 sometimes fails even if there is nothing wrong. Stop testing the ratio, and just return information about the speed and number of monitor messages. The testcase will still serve as a smoke test of the +zdbbl option. --- erts/emulator/test/distribution_SUITE.erl | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl index 78d67ef2ae..dc7afa381b 100644 --- a/erts/emulator/test/distribution_SUITE.erl +++ b/erts/emulator/test/distribution_SUITE.erl @@ -165,15 +165,7 @@ bulk_send_bigbig(Config) when is_list(Config) -> [Rate1,Rate2,MonitorCount1, MonitorCount2,Ratio]), Comment = lists:flatten(Comment0), - if - %% A somewhat arbitrary ratio, but hopefully one that will - %% accommodate a wide range of CPU speeds. - Ratio > 8.0 -> - {comment,Comment}; - true -> - io:put_chars(Comment), - ct:fail(ratio_too_low) - end. + {comment,Comment}. bulk_sendsend2(Terms, BinSize, BusyBufSize) -> ct:timetrap({seconds, 30}), -- cgit v1.2.3 From 1bb171a7c27fcb79435a915bac834a4013b5f0dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 1 Jun 2017 07:29:23 +0200 Subject: Contain damage cause by spawn_opt_max_heap_size failing If process_SUITE:spawn_opt_max_heap_size/1 failed, the default value for the maximum heap size could have been changed. That would cause other test cases that spawned huge processes to fail. Contain the damage by always restoring the default value for max_heap_size in end_per_testcase/2. --- erts/emulator/test/process_SUITE.erl | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index a65c3f0cad..180311202f 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -134,6 +134,11 @@ init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> [{testcase, Func}|Config]. end_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + %% Restore max_heap_size to default value. + erlang:system_flag(max_heap_size, + #{size => 0, + kill => true, + error_logger => true}), ok. fun_spawn(Fun) -> -- cgit v1.2.3 From ff1234e3eba1889a9b8cd81cc03f38cac78a67fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 1 Jun 2017 10:32:13 +0200 Subject: Robustify process_SUITE:spawn_opt_max_heap_size/1 process_SUITE starts os_mon in init_per_suite/1. Therefore, there may be occasional alarm info messages received. Make sure that they are ignored and don't cause the test fail to fail. Also, get rid of the flush/0 function that discards all messages in the message queue. Instead, be more selective and only discard {error, ...} messages. --- erts/emulator/test/process_SUITE.erl | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index 180311202f..4204d12eb3 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -2074,6 +2074,7 @@ max_heap_size_test(Option, Size, Kill, ErrorLogger) -> end, if ErrorLogger -> receive + %% There must be at least one error message. {error, _, {emulator, _, [Pid|_]}} -> ok end; @@ -2086,22 +2087,33 @@ max_heap_size_test(Option, Size, Kill, ErrorLogger) -> {'DOWN', Ref, process, Pid, die} -> ok end, - flush(); + %% If the process was not killed, the limit may have + %% been reached more than once and there may be + %% more {error, ...} messages left. + receive_error_messages(Pid); true -> ok end, + + %% Make sure that there are no unexpected messages. + receive_unexpected(). + +receive_error_messages(Pid) -> receive - M -> - ct:fail({unexpected_message, M}) - after 10 -> + {error, _, {emulator, _, [Pid|_]}} -> + receive_error_messages(Pid) + after 1000 -> ok end. -flush() -> +receive_unexpected() -> receive - _M -> - flush() - after 1000 -> + {info_report, _, _} -> + %% May be an alarm message from os_mon. Ignore. + receive_unexpected(); + M -> + ct:fail({unexpected_message, M}) + after 10 -> ok end. -- cgit v1.2.3 From 6a18795542432fb3f8ba1d4306ec28d6a9250f3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 1 Jun 2017 14:51:20 +0200 Subject: Remove obsolete old_scheduler_SUITE old_scheduler_SUITE was written before the SMP emulator. It does not test anything that scheduler_SUITE does not test. Keeping it wastes time when running the emulator test suite, and does not help us find any bugs that scheduler_SUITE would find. --- erts/emulator/test/Makefile | 1 - erts/emulator/test/old_scheduler_SUITE.erl | 384 ----------------------------- 2 files changed, 385 deletions(-) delete mode 100644 erts/emulator/test/old_scheduler_SUITE.erl (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index 2479ccc01f..fcd7244ae9 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -117,7 +117,6 @@ MODULES= \ tracer_SUITE \ tracer_test \ scheduler_SUITE \ - old_scheduler_SUITE \ port_trace_SUITE \ unique_SUITE \ z_SUITE \ diff --git a/erts/emulator/test/old_scheduler_SUITE.erl b/erts/emulator/test/old_scheduler_SUITE.erl deleted file mode 100644 index 8515a87df8..0000000000 --- a/erts/emulator/test/old_scheduler_SUITE.erl +++ /dev/null @@ -1,384 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2016. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - --module(old_scheduler_SUITE). - --include_lib("common_test/include/ct.hrl"). - --export([all/0, suite/0, - init_per_testcase/2, end_per_testcase/2]). --export([equal/1, many_low/1, few_low/1, max/1, high/1]). - -suite() -> - [{ct_hooks,[ts_install_cth]}, - {timetrap, {minutes, 11}}]. - -all() -> - case catch erlang:system_info(modified_timing_level) of - Level when is_integer(Level) -> - {skipped, - "Modified timing (level " ++ - integer_to_list(Level) ++ - ") is enabled. Testcases gets messed " - "up by modfied timing."}; - _ -> [equal, many_low, few_low, max, high] - end. - - -%%----------------------------------------------------------------------------------- -%% TEST SUITE DESCRIPTION -%% -%% The test case function spawns two controlling processes: Starter and Receiver. -%% Starter spawns a number of prio A and a number of prio B test processes. Each -%% test process loops for a number of times, sends a report to the Receiver, then -%% loops again. For each report, the Receiver increases a counter that corresponds -%% to the priority of the sender. After a certain amount of time, the Receiver -%% sends the collected data to the main test process and waits for the test case -%% to terminate. From this data, it's possible to calculate the average run time -%% relationship between the prio A and B test processes. -%% -%% Note that in order to be able to run tests with high or max prio test processes, -%% the main test process and the Receiver needs to run at max prio, or they will -%% be starved by the test processes. The controlling processes must not wait for -%% messages from a normal (or low) prio process while max or high prio test processes -%% are running (which happens e.g. if an io function is called). -%%----------------------------------------------------------------------------------- - -init_per_testcase(_Case, Config) -> - %% main test process needs max prio - Prio = process_flag(priority, max), - MS = erlang:system_flag(multi_scheduling, block_normal), - [{prio,Prio},{multi_scheduling, MS}|Config]. - -end_per_testcase(_Case, Config) -> - erlang:system_flag(multi_scheduling, unblock_normal), - Prio=proplists:get_value(prio, Config), - process_flag(priority, Prio), - ok. - -ok(Config) when is_list(Config) -> - case proplists:get_value(multi_scheduling, Config) of - blocked -> - {comment, - "Multi-scheduling blocked during test. This testcase was not " - "written to work with multiple schedulers."}; - _ -> ok - end. - -%% Run equal number of low and normal prio processes. - -equal(Config) when is_list(Config) -> - Self = self(), - - %% specify number of test processes to run - Normal = {normal,500}, - Low = {low,500}, - - %% specify time of test (in seconds) - Time = 30, - - %% start controllers - Receiver = - spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Normal, Low) end), - Starter = - spawn(fun() -> starter(Normal, Low, Receiver) end), - - %% receive test data from Receiver - {NRs,NAvg,LRs,LAvg,Ratio} = - receive - {Receiver,Res} -> Res - end, - - %% stop controllers and test processes - exit(Starter, kill), - exit(Receiver, kill), - - io:format("Reports: ~w normal (~w/proc), ~w low (~w/proc). Ratio: ~w~n", - [NRs,NAvg,LRs,LAvg,Ratio]), - - %% runtime ratio between normal and low should be ~8 - if Ratio < 7.5 ; Ratio > 8.5 -> - ct:fail({bad_ratio,Ratio}); - true -> - ok(Config) - end. - - -%% Run many low and few normal prio processes. - -many_low(Config) when is_list(Config) -> - Self = self(), - Normal = {normal,1}, - Low = {low,1000}, - - %% specify time of test (in seconds) - Time = 30, - - Receiver = - spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Normal, Low) end), - Starter = - spawn(fun() -> starter(Normal, Low, Receiver) end), - {NRs,NAvg,LRs,LAvg,Ratio} = - receive - {Receiver,Res} -> Res - end, - exit(Starter, kill), - exit(Receiver, kill), - io:format("Reports: ~w normal (~w/proc), ~w low (~w/proc). Ratio: ~w~n", - [NRs,NAvg,LRs,LAvg,Ratio]), - if Ratio < 7.5 ; Ratio > 8.5 -> - ct:fail({bad_ratio,Ratio}); - true -> - ok(Config) - end. - - -%% Run few low and many normal prio processes. - -few_low(Config) when is_list(Config) -> - Self = self(), - Normal = {normal,1000}, - Low = {low,1}, - - %% specify time of test (in seconds) - Time = 30, - - Receiver = - spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Normal, Low) end), - Starter = - spawn(fun() -> starter(Normal, Low, Receiver) end), - {NRs,NAvg,LRs,LAvg,Ratio} = - receive - {Receiver,Res} -> Res - end, - exit(Starter, kill), - exit(Receiver, kill), - io:format("Reports: ~w normal (~w/proc), ~w low (~w/proc). Ratio: ~w~n", - [NRs,NAvg,LRs,LAvg,Ratio]), - if Ratio < 7.0 ; Ratio > 8.5 -> - ct:fail({bad_ratio,Ratio}); - true -> - ok(Config) - end. - - -%% Run max prio processes and verify they get at least as much -%% runtime as high, normal and low. - -max(Config) when is_list(Config) -> - max = process_flag(priority, max), % should already be max (init_per_tc) - Self = self(), - Max = {max,2}, - High = {high,2}, - Normal = {normal,100}, - Low = {low,100}, - - %% specify time of test (in seconds) - Time = 30, - - Receiver1 = - spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Max, High) end), - Starter1 = - spawn(fun() -> starter(Max, High, Receiver1) end), - {M1Rs,M1Avg,HRs,HAvg,Ratio1} = - receive - {Receiver1,Res1} -> Res1 - end, - exit(Starter1, kill), - exit(Receiver1, kill), - io:format("Reports: ~w max (~w/proc), ~w high (~w/proc). Ratio: ~w~n", - [M1Rs,M1Avg,HRs,HAvg,Ratio1]), - if Ratio1 < 1.0 -> - ct:fail({bad_ratio,Ratio1}); - true -> - ok(Config) - end, - - Receiver2 = - spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Max, Normal) end), - Starter2 = - spawn(fun() -> starter(Max, Normal, Receiver2) end), - {M2Rs,M2Avg,NRs,NAvg,Ratio2} = - receive - {Receiver2,Res2} -> Res2 - end, - exit(Starter2, kill), - exit(Receiver2, kill), - io:format("Reports: ~w max (~w/proc), ~w normal (~w/proc). Ratio: ~w~n", - [M2Rs,M2Avg,NRs,NAvg,Ratio2]), - if Ratio2 < 1.0 -> - ct:fail({bad_ratio,Ratio2}); - true -> - ok - end, - - Receiver3 = - spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, Max, Low) end), - Starter3 = - spawn(fun() -> starter(Max, Low, Receiver3) end), - {M3Rs,M3Avg,LRs,LAvg,Ratio3} = - receive - {Receiver3,Res3} -> Res3 - end, - exit(Starter3, kill), - exit(Receiver3, kill), - io:format("Reports: ~w max (~w/proc), ~w low (~w/proc). Ratio: ~w~n", - [M3Rs,M3Avg,LRs,LAvg,Ratio3]), - if Ratio3 < 1.0 -> - ct:fail({bad_ratio,Ratio3}); - true -> - ok(Config) - end. - - -%% Run high prio processes and verify they get at least as much -%% runtime as normal and low. - -high(Config) when is_list(Config) -> - max = process_flag(priority, max), % should already be max (init_per_tc) - Self = self(), - High = {high,2}, - Normal = {normal,100}, - Low = {low,100}, - - %% specify time of test (in seconds) - Time = 30, - - Receiver1 = - spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, High, Normal) end), - Starter1 = - spawn(fun() -> starter(High, Normal, Receiver1) end), - {H1Rs,H1Avg,NRs,NAvg,Ratio1} = - receive - {Receiver1,Res1} -> Res1 - end, - exit(Starter1, kill), - exit(Receiver1, kill), - io:format("Reports: ~w high (~w/proc), ~w normal (~w/proc). Ratio: ~w~n", - [H1Rs,H1Avg,NRs,NAvg,Ratio1]), - if Ratio1 < 1.0 -> - ct:fail({bad_ratio,Ratio1}); - true -> - ok - end, - - Receiver2 = - spawn(fun() -> receiver(erlang:monotonic_time(), Time, Self, High, Low) end), - Starter2 = - spawn(fun() -> starter(High, Low, Receiver2) end), - {H2Rs,H2Avg,LRs,LAvg,Ratio2} = - receive - {Receiver2,Res2} -> Res2 - end, - exit(Starter2, kill), - exit(Receiver2, kill), - io:format("Reports: ~w high (~w/proc), ~w low (~w/proc). Ratio: ~w~n", - [H2Rs,H2Avg,LRs,LAvg,Ratio2]), - if Ratio2 < 1.0 -> - ct:fail({bad_ratio,Ratio2}); - true -> - ok(Config) - end. - - -%%----------------------------------------------------------------------------------- -%% Controller processes and help functions -%%----------------------------------------------------------------------------------- - -receiver(T0, TimeSec, Main, {P1,P1N}, {P2,P2N}) -> - %% prio should be max so that mailbox doesn't overflow - process_flag(priority, max), - receiver(T0, TimeSec*1000, Main, P1,P1N,0, P2,P2N,0, 100000). - -%% uncomment lines below to get life sign (debug) -receiver(T0, Time, Main, P1,P1N,P1Rs, P2,P2N,P2Rs, 0) -> - % T = erlang:convert_time_unit(erlang:monotonic_time() - T0, native, millisecond), - % erlang:display({round(T/1000),P1Rs,P2Rs}), - receiver(T0, Time, Main, P1,P1N,P1Rs, P2,P2N,P2Rs, 100000); - -receiver(T0, Time, Main, P1,P1N,P1Rs, P2,P2N,P2Rs, C) -> - Remain = Time - erlang:convert_time_unit(erlang:monotonic_time() - T0, - native, millisecond), % test time remaining - Remain1 = if Remain < 0 -> - 0; - true -> - Remain - end, - {P1Rs1,P2Rs1} = - receive - {_Pid,P1} -> % report from a P1 process - {P1Rs+1,P2Rs}; - {_Pid,P2} -> % report from a P2 process - {P1Rs,P2Rs+1} - after Remain1 -> - {P1Rs,P2Rs} - end, - if Remain > 0 -> % keep going - receiver(T0, Time, Main, P1,P1N,P1Rs1, P2,P2N,P2Rs1, C-1); - true -> % finish - %% calculate results and send to main test process - P1Avg = P1Rs1/P1N, - P2Avg = P2Rs1/P2N, - Ratio = if P2Avg < 1.0 -> P1Avg; - true -> P1Avg/P2Avg - end, - Main ! {self(),{P1Rs1,round(P1Avg),P2Rs1,round(P2Avg),Ratio}}, - flush_loop() - end. - -starter({P1,P1N}, {P2,P2N}, Receiver) -> - %% start N1 processes with prio P1 - start_p(P1, P1N, Receiver), - %% start N2 processes with prio P2 - start_p(P2, P2N, Receiver), - erlang:display({started,P1N+P2N}), - flush_loop(). - -start_p(_, 0, _) -> - ok; -start_p(Prio, N, Receiver) -> - spawn_link(fun() -> p(Prio, Receiver) end), - start_p(Prio, N-1, Receiver). - -p(Prio, Receiver) -> - %% set process priority - process_flag(priority, Prio), - p_loop(0, Prio, Receiver). - -p_loop(100, Prio, Receiver) -> - receive after 0 -> ok end, - %% if Receiver gone, we're done - case is_process_alive(Receiver) of - false -> exit(bye); - true -> ok - end, - %% send report - Receiver ! {self(),Prio}, - p_loop(0, Prio, Receiver); - -p_loop(N, Prio, Receiver) -> - p_loop(N+1, Prio, Receiver). - - -flush_loop() -> - receive _ -> - ok - end, - flush_loop(). -- cgit v1.2.3 From 7aa347e1f911f1bcef026c08e32cc4eed280ce38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 1 Jun 2017 15:16:00 +0200 Subject: same_time_yielding/1: Avoid failing if there are many schedulers On a computer with 32 schedulers, there would be 9632 (301*32) 'timeout' message in the receive queue. Receiving them with a selective receive (matching on the timer ID) is quite slow. Change the test case to read out the queue in the order the messages are stored in the queue. --- erts/emulator/test/timer_bif_SUITE.erl | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/timer_bif_SUITE.erl b/erts/emulator/test/timer_bif_SUITE.erl index 7cbd93a0f3..a977eb41c4 100644 --- a/erts/emulator/test/timer_bif_SUITE.erl +++ b/erts/emulator/test/timer_bif_SUITE.erl @@ -488,24 +488,40 @@ registered_process(Config) when is_list(Config) -> same_time_yielding(Config) when is_list(Config) -> Mem = mem(), + Ref = make_ref(), SchdlrsOnln = erlang:system_info(schedulers_online), Tmo = erlang:monotonic_time(millisecond) + 3000, Tmrs = lists:map(fun (I) -> process_flag(scheduler, (I rem SchdlrsOnln) + 1), - erlang:start_timer(Tmo, self(), hej, [{abs, true}]) + erlang:start_timer(Tmo, self(), Ref, [{abs, true}]) end, lists:seq(1, (?TIMEOUT_YIELD_LIMIT*3+1)*SchdlrsOnln)), true = mem_larger_than(Mem), - lists:foreach(fun (Tmr) -> receive {timeout, Tmr, hej} -> ok end end, Tmrs), + receive_all_timeouts(length(Tmrs), Ref), Done = erlang:monotonic_time(millisecond), true = Done >= Tmo, + MsAfterTmo = Done - Tmo, + io:format("Done ~p ms after Tmo\n", [MsAfterTmo]), case erlang:system_info(build_type) of - opt -> true = Done < Tmo + 200; - _ -> true = Done < Tmo + 1000 + opt -> + true = MsAfterTmo < 200; + _ -> + true = MsAfterTmo < 1000 end, Mem = mem(), ok. +%% Read out all timeouts in receive queue order. This is efficient +%% even if there are very many messages. + +receive_all_timeouts(0, _Ref) -> + ok; +receive_all_timeouts(N, Ref) -> + receive + {timeout, _Tmr, Ref} -> + receive_all_timeouts(N-1, Ref) + end. + same_time_yielding_with_cancel(Config) when is_list(Config) -> same_time_yielding_with_cancel_test(false, false). -- cgit v1.2.3 From 46b62dea54a230e46bbadfec7f119ff5ab513e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 2 Jun 2017 11:41:48 +0200 Subject: Stabilize call_with_huge_message_queue/1 Time measurements are always tricky, particulary on virtual hosts. On one particular virtual host, the measured times were often 0. Measuring the time for 100 calls instead of 10 calls helps, but 0 can still be returned, so we will also need to discard measurements that return 0 and try again. --- erts/emulator/test/receive_SUITE.erl | 55 +++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 20 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/receive_SUITE.erl b/erts/emulator/test/receive_SUITE.erl index 83653a7a36..c7d5a3f5a0 100644 --- a/erts/emulator/test/receive_SUITE.erl +++ b/erts/emulator/test/receive_SUITE.erl @@ -39,25 +39,43 @@ groups() -> call_with_huge_message_queue(Config) when is_list(Config) -> Pid = spawn_link(fun echo_loop/0), - - {Time,ok} = tc(fun() -> calls(10, Pid) end), - - [self() ! {msg,N} || N <- lists:seq(1, 500000)], + _WarmUpTime = time_calls(Pid), + Time = time_calls(Pid), + _ = [self() ! {msg,N} || N <- lists:seq(1, 500000)], + io:format("Time for empty message queue: ~p", [Time]), erlang:garbage_collect(), - {NewTime1,ok} = tc(fun() -> calls(10, Pid) end), - {NewTime2,ok} = tc(fun() -> calls(10, Pid) end), + call_with_huge_message_queue_1(Pid, Time, 5). + +call_with_huge_message_queue_1(_Pid, _Time, 0) -> + ct:fail(bad_ratio); +call_with_huge_message_queue_1(Pid, Time, NumTries) -> + HugeTime = time_calls(Pid), + io:format("Time for huge message queue: ~p", [HugeTime]), + + case (HugeTime+1) / (Time+1) of + Q when Q < 10 -> + ok; + Q -> + io:format("Too high ratio: ~p\n", [Q]), + call_with_huge_message_queue_1(Pid, Time, NumTries-1) + end. - io:format("Time for empty message queue: ~p", [Time]), - io:format("Time1 for huge message queue: ~p", [NewTime1]), - io:format("Time2 for huge message queue: ~p", [NewTime2]), - - case hd(lists:sort([(NewTime1+1) / (Time+1), (NewTime2+1) / (Time+1)])) of - Q when Q < 10 -> - ok; - Q -> - ct:fail("Best Q = ~p", [Q]) - end, - ok. +%% Time a number calls. Try to avoid returning a zero time. +time_calls(Pid) -> + time_calls(Pid, 10). + +time_calls(_Pid, 0) -> + 0; +time_calls(Pid, NumTries) -> + case timer:tc(fun() -> calls(Pid) end) of + {0,ok} -> + time_calls(Pid, NumTries-1); + {Time,ok} -> + Time + end. + +calls(Pid) -> + calls(100, Pid). calls(0, _) -> ok; calls(N, Pid) -> @@ -108,6 +126,3 @@ echo_loop() -> Pid ! {Ref,Msg}, echo_loop() end. - -tc(Fun) -> - timer:tc(erlang, apply, [Fun,[]]). -- cgit v1.2.3 From e7377ce9f0a6a37973baca55d3e4ee27380b9313 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 12 Jun 2017 16:21:18 +0200 Subject: after_SUITE: Don't leave a process running --- erts/emulator/test/after_SUITE.erl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/after_SUITE.erl b/erts/emulator/test/after_SUITE.erl index b1f7e06bf5..6409f0b336 100644 --- a/erts/emulator/test/after_SUITE.erl +++ b/erts/emulator/test/after_SUITE.erl @@ -45,13 +45,15 @@ all() -> %% Tests for an old round-off error in 'receive after'." t_after(Config) when is_list(Config) -> - spawn(fun frequent_process/0), + Frequent = spawn_link(fun frequent_process/0), Period = test_server:minutes(1), Before = erlang:monotonic_time(), receive after Period -> - After = erlang:monotonic_time(), - report(Period, Before, After) + After = erlang:monotonic_time(), + unlink(Frequent), + exit(Frequent, die), + report(Period, Before, After) end. report(Period, Before, After) -> -- cgit v1.2.3 From 6b25d2451a870a13965e0b21dd99efe115db4c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 12 Jun 2017 15:49:52 +0200 Subject: busy_port_SUITE: Eliminate 'export_all' --- erts/emulator/test/busy_port_SUITE.erl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/busy_port_SUITE.erl b/erts/emulator/test/busy_port_SUITE.erl index 7094cee992..ce643872e5 100644 --- a/erts/emulator/test/busy_port_SUITE.erl +++ b/erts/emulator/test/busy_port_SUITE.erl @@ -24,14 +24,15 @@ io_to_busy/1, message_order/1, send_3/1, system_monitor/1, no_trap_exit/1, no_trap_exit_unlinked/1, trap_exit/1, multiple_writers/1, - hard_busy_driver/1, soft_busy_driver/1]). - --compile(export_all). + hard_busy_driver/1, soft_busy_driver/1, + scheduling_delay_busy/1, + scheduling_delay_busy_nosuspend/1, + scheduling_busy_link/1]). -include_lib("common_test/include/ct.hrl"). %% Internal exports. --export([init/2]). +-export([init/2,process_init/2,ack/2,call/2,cast/2]). suite() -> [{ct_hooks,[ts_install_cth]}, -- cgit v1.2.3 From c7b5246935a924db24610edf8201c5a553206f87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 12 Jun 2017 15:51:37 +0200 Subject: busy_port_SUITE: Eliminate warnings for unused variables --- erts/emulator/test/busy_port_SUITE.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/busy_port_SUITE.erl b/erts/emulator/test/busy_port_SUITE.erl index ce643872e5..b1600c31bb 100644 --- a/erts/emulator/test/busy_port_SUITE.erl +++ b/erts/emulator/test/busy_port_SUITE.erl @@ -135,7 +135,7 @@ message_order(Config) when is_list(Config) -> ok. send_to_busy_1(Parent) -> - {Owner, Slave} = get_slave(), + {_Owner, Slave} = get_slave(), (catch port_command(Slave, "set_me_busy")), (catch port_command(Slave, "hello")), (catch port_command(Slave, "hello again")), @@ -344,7 +344,7 @@ multiple_writers(Config) when is_list(Config) -> ok. quick_writer() -> - {Owner, Port} = get_slave(), + {_Owner, Port} = get_slave(), (catch port_command(Port, "port to busy")), (catch port_command(Port, "lock me")), ok. -- cgit v1.2.3 From c75bc0ef433caa42cebcd8e3c8dd7a5f0c4fd408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 12 Jun 2017 16:52:10 +0200 Subject: busy_port_SUITE: Ensure that all created procesesses are killed --- erts/emulator/test/busy_port_SUITE.erl | 42 ++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/busy_port_SUITE.erl b/erts/emulator/test/busy_port_SUITE.erl index b1600c31bb..644848daf5 100644 --- a/erts/emulator/test/busy_port_SUITE.erl +++ b/erts/emulator/test/busy_port_SUITE.erl @@ -20,7 +20,7 @@ -module(busy_port_SUITE). --export([all/0, suite/0, end_per_testcase/2, +-export([all/0, suite/0, init_per_testcase/2, end_per_testcase/2, io_to_busy/1, message_order/1, send_3/1, system_monitor/1, no_trap_exit/1, no_trap_exit_unlinked/1, trap_exit/1, multiple_writers/1, @@ -45,6 +45,11 @@ all() -> scheduling_delay_busy,scheduling_delay_busy_nosuspend, scheduling_busy_link]. +init_per_testcase(_Case, Config) when is_list(Config) -> + Killer = spawn(fun() -> killer_loop([]) end), + register(killer_process, Killer), + Config. + end_per_testcase(_Case, Config) when is_list(Config) -> case whereis(busy_drv_server) of undefined -> @@ -58,8 +63,38 @@ end_per_testcase(_Case, Config) when is_list(Config) -> ok end end, + kill_processes(), Config. +kill_processes() -> + killer_process ! {get_pids,self()}, + receive + {pids_to_kill,Pids} -> ok + end, + _ = [begin + case erlang:is_process_alive(P) of + true -> + io:format("Killing ~p\n", [P]); + false -> + ok + end, + unlink(P), + exit(P, kill) + end || P <- Pids], + ok. + +killer_loop(Pids) -> + receive + {add_pid,Pid} -> + killer_loop([Pid|Pids]); + {get_pids,To} -> + To ! {pids_to_kill,Pids} + end. + +kill_me(Pid) -> + killer_process ! {add_pid,Pid}, + Pid. + %% Tests I/O operations to a busy port, to make sure a suspended send %% operation is correctly restarted. This used to crash Beam. @@ -713,6 +748,7 @@ run_scenario([],Vars) -> run_command(_M,spawn,{Args,Opts}) -> Pid = spawn_opt(fun() -> apply(?MODULE,process_init,Args) end,[link|Opts]), + kill_me(Pid), pal("spawn(~p): ~p",[Args,Pid]), Pid; run_command(M,spawn,Args) -> @@ -808,7 +844,9 @@ fun_spawn(Fun) -> fun_spawn(Fun, []). fun_spawn(Fun, Args) -> - spawn_link(erlang, apply, [Fun, Args]). + Pid = spawn_link(erlang, apply, [Fun, Args]), + kill_me(Pid), + Pid. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% These routines provide a port which will become busy when the -- cgit v1.2.3 From 0725fe8296204a61f3dbc57142bfd458a45dd547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 13 Jun 2017 07:10:39 +0200 Subject: Add informational test case z_SUITE:leaked_processes/1 Add z_SUITE:leaked_processes/1 to print the process information for all new processes created during execution of the emulator test suite. Test cases are not supposed leak processes, because that could disturb later test cases. --- erts/emulator/test/a_SUITE.erl | 48 ++++++++++++++++++++++++++++++++++-------- erts/emulator/test/z_SUITE.erl | 33 +++++++++++++++++++++++++++-- 2 files changed, 70 insertions(+), 11 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/a_SUITE.erl b/erts/emulator/test/a_SUITE.erl index 880c5a5821..07922f9942 100644 --- a/erts/emulator/test/a_SUITE.erl +++ b/erts/emulator/test/a_SUITE.erl @@ -29,25 +29,55 @@ -include_lib("common_test/include/ct.hrl"). --export([all/0, suite/0, - long_timers/1, pollset_size/1]). +-export([all/0, suite/0, init_per_suite/1, end_per_suite/1, + leaked_processes/1, long_timers/1, pollset_size/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. -all() -> - [long_timers, pollset_size]. +all() -> + [leaked_processes, long_timers, pollset_size]. + +%% Start some system servers now to avoid having them +%% reported as leaks. + +init_per_suite(Config) when is_list(Config) -> + %% Ensure inet_gethost_native port program started, in order to + %% allow other suites to use it... + inet_gethost_native:gethostbyname("localhost"), + + %% Start the timer server. + timer:start(), + + Config. + +end_per_suite(Config) when is_list(Config) -> + Config. + +leaked_processes(Config) when is_list(Config) -> + Parent = self(), + Go = make_ref(), + spawn(fun () -> + Name = leaked_processes__process_holder, + true = register(Name, self()), + Ps = processes(), + Parent ! Go, + receive + {get_initial_processes, Pid} -> + Pid ! {initial_processes, Ps} + end + end), + receive Go -> ok end, + {comment, "Testcase started! This test will run in parallel with the " + "erts testsuite and ends in the z_SUITE:leaked_processes/1 testcase."}. long_timers(Config) when is_list(Config) -> Dir = proplists:get_value(data_dir, Config), long_timers_test:start(Dir), {comment, "Testcase started! This test will run in parallel with the " - "erts testsuite and ends in the z_SUITE:long_timers testcase."}. + "erts testsuite and ends in the z_SUITE:long_timers/1 testcase."}. pollset_size(Config) when is_list(Config) -> - %% Ensure inet_gethost_native port program started, in order to - %% allow other suites to use it... - inet_gethost_native:gethostbyname("localhost"), Parent = self(), Go = make_ref(), spawn(fun () -> @@ -63,7 +93,7 @@ pollset_size(Config) when is_list(Config) -> end), receive Go -> ok end, {comment, "Testcase started! This test will run in parallel with the " - "erts testsuite and ends in the z_SUITE:pollset_size testcase."}. + "erts testsuite and ends in the z_SUITE:pollset_size/1 testcase."}. %% %% Internal functions... diff --git a/erts/emulator/test/z_SUITE.erl b/erts/emulator/test/z_SUITE.erl index a2b267543f..feea7432a9 100644 --- a/erts/emulator/test/z_SUITE.erl +++ b/erts/emulator/test/z_SUITE.erl @@ -36,7 +36,8 @@ -export([schedulers_alive/1, node_container_refc_check/1, long_timers/1, pollset_size/1, - check_io_debug/1, get_check_io_info/0]). + check_io_debug/1, get_check_io_info/0, + leaked_processes/1]). suite() -> [{ct_hooks,[ts_install_cth]}, @@ -44,7 +45,10 @@ suite() -> all() -> [schedulers_alive, node_container_refc_check, - long_timers, pollset_size, check_io_debug]. + long_timers, pollset_size, check_io_debug, + %% Make sure that the leaked_processes/1 is always + %% run last. + leaked_processes]. %%% %%% The test cases ------------------------------------------------------------- @@ -285,6 +289,31 @@ has_gethost([P|T]) -> has_gethost([]) -> false. +leaked_processes(Config) when is_list(Config) -> + %% Replace the defualt timetrap with a timetrap with + %% known pid. + test_server:timetrap_cancel(), + Dog = test_server:timetrap(test_server:minutes(5)), + + Name = leaked_processes__process_holder, + Name ! {get_initial_processes, self()}, + receive + {initial_processes, Initial0} -> ok + end, + Initial = ordsets:from_list(Initial0), + + KnownPids = ordsets:from_list([self(),Dog]), + Now0 = ordsets:from_list(processes()), + Now = ordsets:subtract(Now0, KnownPids), + Leaked = ordsets:subtract(Now, Initial), + + _ = [begin + Info = process_info(P) ++ process_info(P, [current_stacktrace]), + io:format("~p: ~p\n", [P,Info]) + end || P <- Leaked], + Comment = lists:flatten(io_lib:format("~p process(es)", + [length(Leaked)])), + {comment, Comment}. %% %% Internal functions... -- cgit v1.2.3 From a54014638c6a1cd0a3e7b1ee36998756a475684b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 13 Jun 2017 10:00:15 +0200 Subject: message_queue_data_SUITE: Don't leave processes running --- erts/emulator/test/message_queue_data_SUITE.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/message_queue_data_SUITE.erl b/erts/emulator/test/message_queue_data_SUITE.erl index e084b9482d..0fd86155fb 100644 --- a/erts/emulator/test/message_queue_data_SUITE.erl +++ b/erts/emulator/test/message_queue_data_SUITE.erl @@ -169,7 +169,7 @@ total_heap_size(_Config) -> Fun = fun F() -> receive Pid when is_pid(Pid) -> Pid ! ok,F() end end, %% Test that on_heap messages grow the heap even if they are not received - OnPid = spawn_opt(Fun, [{message_queue_data, on_heap}]), + OnPid = spawn_opt(Fun, [{message_queue_data, on_heap},link]), {total_heap_size, OnSize} = erlang:process_info(OnPid, total_heap_size), [OnPid ! lists:duplicate(N,N) || N <- lists:seq(1,100)], OnPid ! self(), receive ok -> ok end, @@ -178,7 +178,7 @@ total_heap_size(_Config) -> true = OnSize < OnSizeAfter, %% Test that off_heap messages do not grow the heap if they are not received - OffPid = spawn_opt(Fun, [{message_queue_data, off_heap}]), + OffPid = spawn_opt(Fun, [{message_queue_data, off_heap},link]), {total_heap_size, OffSize} = erlang:process_info(OffPid, total_heap_size), [OffPid ! lists:duplicate(N,N) || N <- lists:seq(1,100)], OffPid ! self(), receive ok -> ok end, -- cgit v1.2.3 From 23c436e47f3f28b8797626a113361611631e7bf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 13 Jun 2017 10:04:10 +0200 Subject: trace_SUITE: Don't leave processes running --- erts/emulator/test/trace_SUITE.erl | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/trace_SUITE.erl b/erts/emulator/test/trace_SUITE.erl index bd0ea22de9..9ddc8628b6 100644 --- a/erts/emulator/test/trace_SUITE.erl +++ b/erts/emulator/test/trace_SUITE.erl @@ -24,7 +24,8 @@ %%% Tests the trace BIF. %%% --export([all/0, suite/0, link_receive_call_correlation/0, +-export([all/0, suite/0, init_per_testcase/2, end_per_testcase/2, + link_receive_call_correlation/0, receive_trace/1, link_receive_call_correlation/1, self_send/1, timeout_trace/1, send_trace/1, procs_trace/1, dist_procs_trace/1, procs_new_trace/1, @@ -62,6 +63,14 @@ all() -> system_monitor_long_schedule, system_monitor_large_heap_2, bad_flag, trace_delivered]. +init_per_testcase(_Case, Config) -> + [{receiver,spawn(fun receiver/0)}|Config]. + +end_per_testcase(_Case, Config) -> + Receiver = proplists:get_value(receiver, Config), + unlink(Receiver), + exit(Receiver, die), + ok. %% No longer testing anything, just reporting whether cpu_timestamp %% is enabled or not. @@ -83,7 +92,7 @@ cpu_timestamp(Config) when is_list(Config) -> %% Tests that trace(Pid, How, ['receive']) works. receive_trace(Config) when is_list(Config) -> - Receiver = fun_spawn(fun receiver/0), + Receiver = proplists:get_value(receiver, Config), %% Trace the process; make sure that we receive the trace messages. 1 = erlang:trace(Receiver, true, ['receive']), @@ -353,7 +362,7 @@ timeout_trace(Config) when is_list(Config) -> send_trace(Config) when is_list(Config) -> process_flag(trap_exit, true), Sender = fun_spawn(fun sender/0), - Receiver = fun_spawn(fun receiver/0), + Receiver = proplists:get_value(receiver, Config), %% Check that a message sent to another process is traced. 1 = erlang:trace(Sender, true, [send]), @@ -1604,7 +1613,8 @@ suspend_waiting(Config) when is_list(Config) -> %% Test that erlang:trace(new, true, ...) is cleared when tracer dies. new_clear(Config) when is_list(Config) -> - Tracer = spawn(fun receiver/0), + Tracer = proplists:get_value(receiver, Config), + 0 = erlang:trace(new, true, [send, {tracer, Tracer}]), {flags, [send]} = erlang:trace_info(new, flags), {tracer, Tracer} = erlang:trace_info(new, tracer), @@ -1623,7 +1633,7 @@ new_clear(Config) when is_list(Config) -> existing_clear(Config) when is_list(Config) -> Self = self(), - Tracer = fun_spawn(fun receiver/0), + Tracer = proplists:get_value(receiver, Config), N = erlang:trace(existing, true, [send, {tracer, Tracer}]), {flags, [send]} = erlang:trace_info(Self, flags), {tracer, Tracer} = erlang:trace_info(Self, tracer), @@ -1639,27 +1649,30 @@ existing_clear(Config) when is_list(Config) -> %% Test that erlang:trace/3 can be called on processes where the %% tracer has died. OTP-13928 tracer_die(Config) when is_list(Config) -> - Proc = spawn(fun receiver/0), + Proc = spawn_link(fun receiver/0), - Tracer = spawn(fun receiver/0), + Tracer = spawn_link(fun receiver/0), timer:sleep(1), N = erlang:trace(existing, true, [send, {tracer, Tracer}]), {flags, [send]} = erlang:trace_info(Proc, flags), {tracer, Tracer} = erlang:trace_info(Proc, tracer), + unlink(Tracer), exit(Tracer, die), - Tracer2 = spawn(fun receiver/0), + Tracer2 = spawn_link(fun receiver/0), timer:sleep(1), N = erlang:trace(existing, true, [send, {tracer, Tracer2}]), {flags, [send]} = erlang:trace_info(Proc, flags), {tracer, Tracer2} = erlang:trace_info(Proc, tracer), + unlink(Tracer2), exit(Tracer2, die), - Tracer3 = spawn(fun receiver/0), + Tracer3 = spawn_link(fun receiver/0), timer:sleep(1), 1 = erlang:trace(Proc, true, [send, {tracer, Tracer3}]), {flags, [send]} = erlang:trace_info(Proc, flags), {tracer, Tracer3} = erlang:trace_info(Proc, tracer), + unlink(Tracer3), exit(Tracer3, die), ok. -- cgit v1.2.3 From 23e3855559445500f109798373312830d6e746f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 13 Jun 2017 10:07:46 +0200 Subject: trace_bif_SUITE: Don't leave processes running --- erts/emulator/test/trace_bif_SUITE.erl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/trace_bif_SUITE.erl b/erts/emulator/test/trace_bif_SUITE.erl index f60c777ba1..ce9c60d9d9 100644 --- a/erts/emulator/test/trace_bif_SUITE.erl +++ b/erts/emulator/test/trace_bif_SUITE.erl @@ -47,7 +47,7 @@ not_run(Config) when is_list(Config) -> %% Tests switching tracing on and off. trace_on_and_off(Config) when is_list(Config) -> - Pid = spawn(?MODULE, bif_process, []), + Pid = spawn_link(?MODULE, bif_process, []), Self = self(), 1 = erlang:trace(Pid, true, [call,timestamp]), {flags, Flags} = erlang:trace_info(Pid,flags), @@ -59,6 +59,7 @@ trace_on_and_off(Config) when is_list(Config) -> 1 = erlang:trace(Pid, false, [call]), {flags,[]} = erlang:trace_info(Pid,flags), {tracer, []} = erlang:trace_info(Pid,tracer), + unlink(Pid), exit(Pid,kill), ok. @@ -71,7 +72,7 @@ trace_bif_local(Config) when is_list(Config) -> do_trace_bif([local]). do_trace_bif(Flags) -> - Pid = spawn(?MODULE, bif_process, []), + Pid = spawn_link(?MODULE, bif_process, []), 1 = erlang:trace(Pid, true, [call]), erlang:trace_pattern({erlang,'_','_'}, [], Flags), Pid ! {do_bif, time, []}, @@ -90,6 +91,7 @@ do_trace_bif(Flags) -> 1 = erlang:trace(Pid, false, [call]), erlang:trace_pattern({erlang,'_','_'}, false, Flags), + unlink(Pid), exit(Pid, die), ok. @@ -121,7 +123,7 @@ trace_bif_timestamp_local(Config) when is_list(Config) -> do_trace_bif_timestamp(Flags, TsType, TsFlags) -> io:format("Testing with TsType=~p TsFlags=~p~n", [TsType, TsFlags]), - Pid=spawn(?MODULE, bif_process, []), + Pid = spawn_link(?MODULE, bif_process, []), 1 = erlang:trace(Pid, true, [call]++TsFlags), erlang:trace_pattern({erlang,'_','_'}, [], Flags), @@ -161,6 +163,7 @@ do_trace_bif_timestamp(Flags, TsType, TsFlags) -> 1 = erlang:trace(Pid, false, [call]), erlang:trace_pattern({erlang,'_','_'}, false, Flags), + unlink(Pid), exit(Pid, die), ok. @@ -179,7 +182,7 @@ trace_bif_return(Config) when is_list(Config) -> do_trace_bif_return(TsType, TsFlags) -> io:format("Testing with TsType=~p TsFlags=~p~n", [TsType, TsFlags]), - Pid=spawn(?MODULE, bif_process, []), + Pid = spawn_link(?MODULE, bif_process, []), 1 = erlang:trace(Pid, true, [call,return_to]++TsFlags), erlang:trace_pattern({erlang,'_','_'}, [{'_',[],[{return_trace}]}], [local]), -- cgit v1.2.3 From 66bfe2f5d977bdac5809a273bd7b30f42063548f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 13 Jun 2017 10:09:31 +0200 Subject: trace_nif_SUITE: Don't leave processes running --- erts/emulator/test/trace_nif_SUITE.erl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/trace_nif_SUITE.erl b/erts/emulator/test/trace_nif_SUITE.erl index 7ac6fce234..5c35a8a83f 100644 --- a/erts/emulator/test/trace_nif_SUITE.erl +++ b/erts/emulator/test/trace_nif_SUITE.erl @@ -80,7 +80,7 @@ trace_nif_meta(Config) when is_list(Config) -> {?MODULE,nif, ["Arg1"]}}), ok. do_trace_nif(Flags) -> - Pid = spawn(?MODULE, nif_process, []), + Pid = spawn_link(?MODULE, nif_process, []), 1 = erlang:trace(Pid, true, [call]), erlang:trace_pattern({?MODULE,nif,'_'}, [], Flags), Pid ! {apply_nif, nif, []}, @@ -123,6 +123,8 @@ do_trace_nif(Flags) -> 1 = erlang:trace(Pid, false, [call]), erlang:trace_pattern({?MODULE,nif,'_'}, false, Flags), + + unlink(Pid), exit(Pid, die), ok. @@ -137,7 +139,7 @@ trace_nif_timestamp_local(Config) when is_list(Config) -> do_trace_nif_timestamp([local]). do_trace_nif_timestamp(Flags) -> - Pid=spawn(?MODULE, nif_process, []), + Pid = spawn_link(?MODULE, nif_process, []), 1 = erlang:trace(Pid, true, [call,timestamp]), erlang:trace_pattern({?MODULE,nif,'_'}, [], Flags), @@ -170,6 +172,7 @@ do_trace_nif_timestamp(Flags) -> 1 = erlang:trace(Pid, false, [call]), erlang:trace_pattern({erlang,'_','_'}, false, Flags), + unlink(Pid), exit(Pid, die), ok. @@ -177,7 +180,7 @@ do_trace_nif_timestamp(Flags) -> trace_nif_return(Config) when is_list(Config) -> load_nif(Config), - Pid=spawn(?MODULE, nif_process, []), + Pid = spawn_link(?MODULE, nif_process, []), 1 = erlang:trace(Pid, true, [call,timestamp,return_to]), erlang:trace_pattern({?MODULE,nif,'_'}, [{'_',[],[{return_trace}]}], [local]), -- cgit v1.2.3 From 11879f00ffddef3c2c118b733e91690ff178a695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 13 Jun 2017 10:24:25 +0200 Subject: tracer_SUITE: Don't leave processes running --- erts/emulator/test/tracer_SUITE.erl | 44 +++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/tracer_SUITE.erl b/erts/emulator/test/tracer_SUITE.erl index 730c43d8c2..c2fa3afd9b 100644 --- a/erts/emulator/test/tracer_SUITE.erl +++ b/erts/emulator/test/tracer_SUITE.erl @@ -70,7 +70,7 @@ init_per_testcase(TC, Config) when TC =:= load; TC =:= reload -> end end), register(tracer_test_config, Pid), - Config; + common_init_per_testcase(Config); init_per_testcase(_, Config) -> DataDir = proplists:get_value(data_dir, Config), case catch tracer_test:enabled(trace_status, self(), self()) of @@ -79,16 +79,52 @@ init_per_testcase(_, Config) -> _ -> tracer_test:load(DataDir) end, + common_init_per_testcase(Config). + +common_init_per_testcase(Config) -> + Killer = erlang:spawn(fun() -> killer_loop([]) end), + register(killer_process, Killer), Config. end_per_testcase(TC, _Config) when TC =:= load; TC =:= reload -> purge(), exit(whereis(tracer_test_config), kill), - ok; + kill_processes(); end_per_testcase(_, _Config) -> purge(), + kill_processes(). + +kill_processes() -> + killer_process ! {get_pids,self()}, + receive + {pids_to_kill,Pids} -> ok + end, + _ = [begin + case erlang:is_process_alive(P) of + true -> + io:format("Killing ~p\n", [P]); + false -> + ok + end, + erlang:unlink(P), + exit(P, kill) + end || P <- Pids], ok. +killer_loop(Pids) -> + receive + {add_pid,Pid} -> + killer_loop([Pid|Pids]); + {get_pids,To} -> + To ! {pids_to_kill,Pids} + end. + +kill_me(Pid) -> + killer_process ! {add_pid,Pid}, + Pid. + +%%% Test cases follow. + load(_Config) -> purge(), 1 = erlang:trace(self(), true, [{tracer, tracer_test, []}, call]), @@ -113,7 +149,6 @@ unload(_Config) -> Pid = erlang:spawn_link(fun() -> ServerFun(0, undefined) end), - Tc = fun(N) -> Pid ! {N, self()}, receive done -> ok after 1000 -> ct:fail(timeout) end, @@ -295,7 +330,7 @@ call_test(Arg) -> spawn(_Config) -> Tc = fun(Pid) -> - Pid ! fun() -> erlang:spawn(lists,seq,[1,10]), ok end + Pid ! fun() -> kill_me(erlang:spawn(lists,seq,[1,10])), ok end end, Expect = @@ -355,6 +390,7 @@ unlink(_Config) -> SPid = erlang:spawn(fun() -> receive _ -> ok end end), erlang:link(SPid), erlang:unlink(SPid), + kill_me(SPid), ok end end, -- cgit v1.2.3 From 8322886e6ac13476d01d6db96d5b50d376cc123e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 13 Jun 2017 10:27:22 +0200 Subject: trace_port_SUITE: Don't leave processes running --- erts/emulator/test/trace_port_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/trace_port_SUITE.erl b/erts/emulator/test/trace_port_SUITE.erl index 5eb27a7b68..140a59782f 100644 --- a/erts/emulator/test/trace_port_SUITE.erl +++ b/erts/emulator/test/trace_port_SUITE.erl @@ -190,7 +190,7 @@ receive_trace(Config) when is_list(Config) -> receive_trace_non_scheduler(Config) when is_list(Config) -> start_tracer(Config), S = self(), - Receiver = spawn( + Receiver = spawn_link( fun() -> receive go -> -- cgit v1.2.3 From a27c69e55f6f10d63135b6323060cf76b41509da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 13 Jun 2017 10:29:06 +0200 Subject: process_SUITE: Don't leave processes running --- erts/emulator/test/process_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index 4204d12eb3..b993bf5c69 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -677,7 +677,7 @@ chk_pi_order([{Arg, _}| Values], [Arg|Args]) -> chk_pi_order(Values, Args). process_info_2_list(Config) when is_list(Config) -> - Proc = spawn(fun () -> receive after infinity -> ok end end), + Proc = spawn_link(fun () -> receive after infinity -> ok end end), register(process_SUITE_process_info_2_list1, self()), register(process_SUITE_process_info_2_list2, Proc), erts_debug:set_internal_state(available_internal_state,true), -- cgit v1.2.3 From f529828f540ad50cc157755fbd19d8b595ee07ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 13 Jun 2017 14:14:26 +0200 Subject: Remove unused functions in test emulator test suites --- erts/emulator/test/a_SUITE.erl | 10 ------ erts/emulator/test/dirty_bif_SUITE.erl | 3 -- erts/emulator/test/distribution_SUITE.erl | 46 ------------------------- erts/emulator/test/driver_SUITE.erl | 6 ---- erts/emulator/test/message_queue_data_SUITE.erl | 2 -- erts/emulator/test/monitor_SUITE.erl | 3 -- erts/emulator/test/receive_SUITE.erl | 3 -- erts/emulator/test/system_info_SUITE.erl | 5 --- erts/emulator/test/time_SUITE.erl | 3 -- erts/emulator/test/trace_port_SUITE.erl | 9 ----- erts/emulator/test/unique_SUITE.erl | 7 ---- 11 files changed, 97 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/a_SUITE.erl b/erts/emulator/test/a_SUITE.erl index 07922f9942..9cc86014ec 100644 --- a/erts/emulator/test/a_SUITE.erl +++ b/erts/emulator/test/a_SUITE.erl @@ -99,15 +99,5 @@ pollset_size(Config) when is_list(Config) -> %% Internal functions... %% -display_check_io(ChkIo) -> - catch erlang:display('--- CHECK IO INFO ---'), - catch erlang:display(ChkIo), - catch erts_debug:set_internal_state(available_internal_state, true), - NoOfErrorFds = (catch element(1, erts_debug:get_internal_state(check_io_debug))), - catch erlang:display({'NoOfErrorFds', NoOfErrorFds}), - catch erts_debug:set_internal_state(available_internal_state, false), - catch erlang:display('--- CHECK IO INFO ---'), - ok. - get_check_io_info() -> z_SUITE:get_check_io_info(). diff --git a/erts/emulator/test/dirty_bif_SUITE.erl b/erts/emulator/test/dirty_bif_SUITE.erl index b8361690e6..981ec4d48d 100644 --- a/erts/emulator/test/dirty_bif_SUITE.erl +++ b/erts/emulator/test/dirty_bif_SUITE.erl @@ -543,9 +543,6 @@ test_dirty_process_access(Start, Test, Finish) -> end, ok = Finish(BifPid). -receive_any() -> - receive M -> M end. - start_node(Config) -> start_node(Config, ""). diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl index dc7afa381b..b4ec99f902 100644 --- a/erts/emulator/test/distribution_SUITE.erl +++ b/erts/emulator/test/distribution_SUITE.erl @@ -2255,52 +2255,6 @@ string_to_utf8_list([CP|CPs]) when is_integer(CP), 16#80 bor (16#3F band CP) | string_to_utf8_list(CPs)]. -utf8_list_to_string([]) -> - []; -utf8_list_to_string([B|Bs]) when is_integer(B), - 0 =< B, - B =< 16#7F -> - [B | utf8_list_to_string(Bs)]; -utf8_list_to_string([B0, B1 | Bs]) when is_integer(B0), - 16#C0 =< B0, - B0 =< 16#DF, - is_integer(B1), - 16#80 =< B1, - B1 =< 16#BF -> - [(((B0 band 16#1F) bsl 6) - bor (B1 band 16#3F)) - | utf8_list_to_string(Bs)]; -utf8_list_to_string([B0, B1, B2 | Bs]) when is_integer(B0), - 16#E0 =< B0, - B0 =< 16#EF, - is_integer(B1), - 16#80 =< B1, - B1 =< 16#BF, - is_integer(B2), - 16#80 =< B2, - B2 =< 16#BF -> - [(((B0 band 16#F) bsl 12) - bor ((B1 band 16#3F) bsl 6) - bor (B2 band 16#3F)) - | utf8_list_to_string(Bs)]; -utf8_list_to_string([B0, B1, B2, B3 | Bs]) when is_integer(B0), - 16#F0 =< B0, - B0 =< 16#F7, - is_integer(B1), - 16#80 =< B1, - B1 =< 16#BF, - is_integer(B2), - 16#80 =< B2, - B2 =< 16#BF, - is_integer(B3), - 16#80 =< B3, - B3 =< 16#BF -> - [(((B0 band 16#7) bsl 18) - bor ((B1 band 16#3F) bsl 12) - bor ((B2 band 16#3F) bsl 6) - bor (B3 band 16#3F)) - | utf8_list_to_string(Bs)]. - mk_pid({NodeName, Creation}, Number, Serial) when is_atom(NodeName) -> <> = term_to_binary(NodeName), mk_pid({NodeNameExt, Creation}, Number, Serial); diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl index e854a5f945..954f3b137f 100644 --- a/erts/emulator/test/driver_SUITE.erl +++ b/erts/emulator/test/driver_SUITE.erl @@ -1750,12 +1750,6 @@ thread_mseg_alloc_cache_clean(Config) when is_list(Config) -> ok end. -mseg_alloc_cci(MsegAllocInfo) -> - {value,{options, OL}} - = lists:keysearch(options, 1, MsegAllocInfo), - {value,{cci,CCI}} = lists:keysearch(cci,1,OL), - CCI. - mseg_alloc_ccc() -> mseg_alloc_ccc(mseg_inst_info(0)). diff --git a/erts/emulator/test/message_queue_data_SUITE.erl b/erts/emulator/test/message_queue_data_SUITE.erl index 0fd86155fb..0d5f4aa0af 100644 --- a/erts/emulator/test/message_queue_data_SUITE.erl +++ b/erts/emulator/test/message_queue_data_SUITE.erl @@ -192,8 +192,6 @@ total_heap_size(_Config) -> %% %% -start_node(Config) -> - start_node(Config, []). start_node(Config, Opts) when is_list(Config), is_list(Opts) -> Pa = filename:dirname(code:which(?MODULE)), Name = list_to_atom(atom_to_list(?MODULE) diff --git a/erts/emulator/test/monitor_SUITE.erl b/erts/emulator/test/monitor_SUITE.erl index 827ed817cc..ed3ab23738 100644 --- a/erts/emulator/test/monitor_SUITE.erl +++ b/erts/emulator/test/monitor_SUITE.erl @@ -974,9 +974,6 @@ generate(_Fun, 0) -> generate(Fun, N) -> [Fun() | generate(Fun, N-1)]. -start_node(Config) -> - start_node(Config, ""). - start_node(Config, Args) -> TestCase = proplists:get_value(testcase, Config), PA = filename:dirname(code:which(?MODULE)), diff --git a/erts/emulator/test/receive_SUITE.erl b/erts/emulator/test/receive_SUITE.erl index c7d5a3f5a0..26eddfd03c 100644 --- a/erts/emulator/test/receive_SUITE.erl +++ b/erts/emulator/test/receive_SUITE.erl @@ -34,9 +34,6 @@ suite() -> all() -> [call_with_huge_message_queue, receive_in_between]. -groups() -> - []. - call_with_huge_message_queue(Config) when is_list(Config) -> Pid = spawn_link(fun echo_loop/0), _WarmUpTime = time_calls(Pid), diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl index 9c71f20279..56522039da 100644 --- a/erts/emulator/test/system_info_SUITE.erl +++ b/erts/emulator/test/system_info_SUITE.erl @@ -363,11 +363,6 @@ mem_workers_call(MWs, Fun, Args) -> end end, MWs). -mem_workers_cast(MWs, Fun, Args) -> - lists:foreach(fun (MW) -> - MW ! {cast, self(), Fun, Args} - end, MWs). - spawn_mem_workers() -> spawn_mem_workers(erlang:system_info(schedulers_online)). diff --git a/erts/emulator/test/time_SUITE.erl b/erts/emulator/test/time_SUITE.erl index 214a549a9d..6b9a358496 100644 --- a/erts/emulator/test/time_SUITE.erl +++ b/erts/emulator/test/time_SUITE.erl @@ -993,9 +993,6 @@ bad_dates() -> {{1996, 4, 30}, {12, 0, -1}}, % Sec {{1996, 4, 30}, {12, 0, 60}}]. -start_node(Config) -> - start_node(Config, ""). - start_node(Config, Args) -> TestCase = proplists:get_value(testcase, Config), PA = filename:dirname(code:which(?MODULE)), diff --git a/erts/emulator/test/trace_port_SUITE.erl b/erts/emulator/test/trace_port_SUITE.erl index 140a59782f..fa6460073a 100644 --- a/erts/emulator/test/trace_port_SUITE.erl +++ b/erts/emulator/test/trace_port_SUITE.erl @@ -349,15 +349,6 @@ huge_data(N) -> P = huge_data(N div 2), [16#1234566,P|P]. -expect() -> - receive - Other -> - ok = io:format("Unexpected; got ~p", [Other]), - ct:fail({unexpected, Other}) - after 200 -> - ok - end. - expect({trace_ts,E1,E2,info,ts}=Message) -> receive {trace_ts,E1,E2,_Info,_Ts}=MessageTs -> diff --git a/erts/emulator/test/unique_SUITE.erl b/erts/emulator/test/unique_SUITE.erl index c5aa80c7b4..3b972b87b5 100644 --- a/erts/emulator/test/unique_SUITE.erl +++ b/erts/emulator/test/unique_SUITE.erl @@ -302,13 +302,6 @@ smaller_valid_uniqint(Int, UinqintInfo) -> smaller_valid_uniqint(Cand, UinqintInfo) end. -int32_to_bigendian_list(Int) -> - 0 = Int bsr 32, - [(Int bsr 24) band 16#ff, - (Int bsr 16) band 16#ff, - (Int bsr 8) band 16#ff, - Int band 16#ff]. - mk_uniqint(Int, #uniqint_info {min_int = MinInt, sched_bits = SchedBits} = _UinqintInfo) -> Int1 = Int - MinInt, -- cgit v1.2.3 From 3ea80da9e908e0802b78e19bd29f4ccc2c7be703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 13 Jun 2017 14:24:41 +0200 Subject: Eliminate warnings for unused variables --- erts/emulator/test/efile_SUITE.erl | 1 - erts/emulator/test/long_timers_test.erl | 2 +- erts/emulator/test/port_SUITE.erl | 2 +- erts/emulator/test/scheduler_SUITE.erl | 5 ++--- erts/emulator/test/system_profile_SUITE.erl | 6 ++++-- erts/emulator/test/time_SUITE.erl | 2 +- erts/emulator/test/unique_SUITE.erl | 1 - 7 files changed, 9 insertions(+), 10 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/efile_SUITE.erl b/erts/emulator/test/efile_SUITE.erl index 6bb8487c4e..eaf6b58c33 100644 --- a/erts/emulator/test/efile_SUITE.erl +++ b/erts/emulator/test/efile_SUITE.erl @@ -74,7 +74,6 @@ file_keys(Dir,Num,FdList,FnList) -> %% Check that the distribution of files over async threads is fair async_dist(Config) when is_list(Config) -> DataDir = proplists:get_value(data_dir,Config), - TestFile = filename:join(DataDir, "existing_file"), Dir = filename:dirname(code:which(?MODULE)), AsyncSizes = [7,10,100,255,256,64,63,65], Max = 0.5, diff --git a/erts/emulator/test/long_timers_test.erl b/erts/emulator/test/long_timers_test.erl index c9a380a229..896ac5e1f6 100644 --- a/erts/emulator/test/long_timers_test.erl +++ b/erts/emulator/test/long_timers_test.erl @@ -175,7 +175,7 @@ had_high_cpu_util(StartTime, ActTo = TargetTo + TimeoutDiff, hcpu(ActTo, TargetTo, UtilData). -hcpu(_ActTo, _TargetTo, [{UT, 0} | _] = UD) -> +hcpu(_ActTo, _TargetTo, [{_UT, 0} | _]) -> missing; %% Util is the integer zero when not supported... %% UT2 =:= UT1 hcpu(ActTo, TargetTo, [{UT, _}, {UT, _} | _] = UD) -> diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index fccbaf13ee..f512fa3a57 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -1042,7 +1042,7 @@ pipe_limit_env_do(Bytes, Cmd, CmdSize) -> %% environ format: KEY=VALUE\0 env_of_bytes(Bytes) when Bytes > 3 -> - Env = [{"X",lists:duplicate(Bytes-3, $x)}]; + [{"X",lists:duplicate(Bytes-3, $x)}]; env_of_bytes(_) -> []. %% White box assumption about payload written to pipe diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl index 8d71df65e7..af33de237c 100644 --- a/erts/emulator/test/scheduler_SUITE.erl +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -799,7 +799,7 @@ update_cpu_info(Config) when is_list(Config) -> unchanged -> ok; changed -> ok end; - {Avail, _} -> + {_Avail, _} -> try adjust_schedulers_online(), case erlang:system_info(schedulers_online) of @@ -848,7 +848,7 @@ update_cpu_info(Config) when is_list(Config) -> bits_in_mask(Mask) -> bits_in_mask(Mask, 0, 0). -bits_in_mask(0, Shift, N) -> +bits_in_mask(0, _Shift, N) -> N; bits_in_mask(Mask, Shift, N) -> case Mask band (1 bsl Shift) of @@ -1143,7 +1143,6 @@ dirty_scheduler_threads(Config) when is_list(Config) -> end. dirty_scheduler_threads_test(Config) -> - SmpSupport = erlang:system_info(smp_support), {Sched, SchedOnln, _} = get_dsstate(Config, ""), {HalfSched, HalfSchedOnln} = {lists:max([1,Sched div 2]), lists:max([1,SchedOnln div 2])}, diff --git a/erts/emulator/test/system_profile_SUITE.erl b/erts/emulator/test/system_profile_SUITE.erl index 2e359b11ce..3a8f862b05 100644 --- a/erts/emulator/test/system_profile_SUITE.erl +++ b/erts/emulator/test/system_profile_SUITE.erl @@ -542,8 +542,10 @@ has_runnable_event(TsType, Events) -> end end, Events). -has_profiler_pid_event([], _) -> false; -has_profiler_pid_event([{profile, Pid, _Activity, _MFA, _TS}|Events], Pid) -> true; +has_profiler_pid_event([], _) -> + false; +has_profiler_pid_event([{profile, Pid, _Activity, _MFA, _TS}|_Events], Pid) -> + true; has_profiler_pid_event([_|Events], Pid) -> has_profiler_pid_event(Events, Pid). diff --git a/erts/emulator/test/time_SUITE.erl b/erts/emulator/test/time_SUITE.erl index 6b9a358496..e01efac86b 100644 --- a/erts/emulator/test/time_SUITE.erl +++ b/erts/emulator/test/time_SUITE.erl @@ -300,7 +300,7 @@ os_system_time_offset() -> had_time_warp(Secs) -> had_time_warp(os_system_time_offset(), Secs). -had_time_warp(OrigOffs, 0) -> +had_time_warp(_OrigOffs, 0) -> false; had_time_warp(OrigOffs, N) -> receive after 1000 -> ok end, diff --git a/erts/emulator/test/unique_SUITE.erl b/erts/emulator/test/unique_SUITE.erl index 3b972b87b5..ab02531de3 100644 --- a/erts/emulator/test/unique_SUITE.erl +++ b/erts/emulator/test/unique_SUITE.erl @@ -308,7 +308,6 @@ mk_uniqint(Int, #uniqint_info {min_int = MinInt, ThrId = Int1 band ((1 bsl SchedBits) - 1), Value = (Int1 bsr SchedBits) band ((1 bsl 64) - 1), 0 = Int1 bsr (SchedBits + 64), - NodeName = atom_to_list(node()), Make = {make_unique_integer, ThrId, Value}, %% erlang:display(Make), Res = erts_debug:get_internal_state(Make), -- cgit v1.2.3 From 43718d3b81d7f3d08e25047e22d579801bbe5044 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Wed, 14 Jun 2017 15:36:21 +0200 Subject: Update copyright year --- erts/emulator/test/a_SUITE.erl | 2 +- erts/emulator/test/after_SUITE.erl | 2 +- erts/emulator/test/bs_construct_SUITE.erl | 2 +- erts/emulator/test/busy_port_SUITE.erl | 2 +- erts/emulator/test/code_SUITE.erl | 2 +- erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c | 2 +- erts/emulator/test/driver_SUITE.erl | 2 +- erts/emulator/test/efile_SUITE.erl | 2 +- erts/emulator/test/evil_SUITE.erl | 2 +- erts/emulator/test/exception_SUITE.erl | 2 +- erts/emulator/test/gc_SUITE.erl | 2 +- erts/emulator/test/hipe_SUITE.erl | 2 +- erts/emulator/test/long_timers_test.erl | 2 +- erts/emulator/test/lttng_SUITE.erl | 2 +- erts/emulator/test/message_queue_data_SUITE.erl | 2 +- erts/emulator/test/monitor_SUITE.erl | 2 +- erts/emulator/test/mtx_SUITE.erl | 2 +- erts/emulator/test/nested_SUITE.erl | 2 +- erts/emulator/test/port_trace_SUITE.erl | 2 +- erts/emulator/test/process_SUITE.erl | 2 +- erts/emulator/test/receive_SUITE.erl | 2 +- erts/emulator/test/signal_SUITE.erl | 2 +- erts/emulator/test/system_profile_SUITE.erl | 2 +- erts/emulator/test/timer_bif_SUITE.erl | 2 +- erts/emulator/test/trace_SUITE.erl | 2 +- erts/emulator/test/trace_bif_SUITE.erl | 2 +- erts/emulator/test/trace_local_SUITE.erl | 2 +- erts/emulator/test/trace_meta_SUITE.erl | 2 +- erts/emulator/test/trace_nif_SUITE.erl | 2 +- erts/emulator/test/trace_port_SUITE.erl | 2 +- erts/emulator/test/tracer_SUITE.erl | 2 +- erts/emulator/test/unique_SUITE.erl | 2 +- 32 files changed, 32 insertions(+), 32 deletions(-) (limited to 'erts/emulator/test') diff --git a/erts/emulator/test/a_SUITE.erl b/erts/emulator/test/a_SUITE.erl index 9cc86014ec..5b04a15b85 100644 --- a/erts/emulator/test/a_SUITE.erl +++ b/erts/emulator/test/a_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2016. All Rights Reserved. +%% Copyright Ericsson AB 2006-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/after_SUITE.erl b/erts/emulator/test/after_SUITE.erl index 6409f0b336..8a34195e8d 100644 --- a/erts/emulator/test/after_SUITE.erl +++ b/erts/emulator/test/after_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/bs_construct_SUITE.erl b/erts/emulator/test/bs_construct_SUITE.erl index 779d81daa5..b79f4b995d 100644 --- a/erts/emulator/test/bs_construct_SUITE.erl +++ b/erts/emulator/test/bs_construct_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/busy_port_SUITE.erl b/erts/emulator/test/busy_port_SUITE.erl index 644848daf5..4e7004a424 100644 --- a/erts/emulator/test/busy_port_SUITE.erl +++ b/erts/emulator/test/busy_port_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index ab0fc0d42c..77321aa50f 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c index 1ab39466db..0321b9898f 100644 --- a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c +++ b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2009-2016. All Rights Reserved. + * Copyright Ericsson AB 2009-2017. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl index 954f3b137f..6810729285 100644 --- a/erts/emulator/test/driver_SUITE.erl +++ b/erts/emulator/test/driver_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/efile_SUITE.erl b/erts/emulator/test/efile_SUITE.erl index eaf6b58c33..f0e1bcf04b 100644 --- a/erts/emulator/test/efile_SUITE.erl +++ b/erts/emulator/test/efile_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/evil_SUITE.erl b/erts/emulator/test/evil_SUITE.erl index fb1954ce37..fc4ac037ac 100644 --- a/erts/emulator/test/evil_SUITE.erl +++ b/erts/emulator/test/evil_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2016. All Rights Reserved. +%% Copyright Ericsson AB 2002-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/exception_SUITE.erl b/erts/emulator/test/exception_SUITE.erl index ad6d8c890f..aaca522da6 100644 --- a/erts/emulator/test/exception_SUITE.erl +++ b/erts/emulator/test/exception_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/gc_SUITE.erl b/erts/emulator/test/gc_SUITE.erl index 2c2cb9c32d..f3942ef416 100644 --- a/erts/emulator/test/gc_SUITE.erl +++ b/erts/emulator/test/gc_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/hipe_SUITE.erl b/erts/emulator/test/hipe_SUITE.erl index 5083f01f34..e62d4260f6 100644 --- a/erts/emulator/test/hipe_SUITE.erl +++ b/erts/emulator/test/hipe_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2016. All Rights Reserved. +%% Copyright Ericsson AB 2016-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/long_timers_test.erl b/erts/emulator/test/long_timers_test.erl index 896ac5e1f6..de1a6e6d32 100644 --- a/erts/emulator/test/long_timers_test.erl +++ b/erts/emulator/test/long_timers_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2016. All Rights Reserved. +%% Copyright Ericsson AB 2006-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/lttng_SUITE.erl b/erts/emulator/test/lttng_SUITE.erl index 1c1952f912..a012fa1da2 100644 --- a/erts/emulator/test/lttng_SUITE.erl +++ b/erts/emulator/test/lttng_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/message_queue_data_SUITE.erl b/erts/emulator/test/message_queue_data_SUITE.erl index 0d5f4aa0af..7f0cbdd885 100644 --- a/erts/emulator/test/message_queue_data_SUITE.erl +++ b/erts/emulator/test/message_queue_data_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2014-2016. All Rights Reserved. +%% Copyright Ericsson AB 2014-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/monitor_SUITE.erl b/erts/emulator/test/monitor_SUITE.erl index ed3ab23738..9d772480d9 100644 --- a/erts/emulator/test/monitor_SUITE.erl +++ b/erts/emulator/test/monitor_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/mtx_SUITE.erl b/erts/emulator/test/mtx_SUITE.erl index 0d6ab5cdb2..843e917dfc 100644 --- a/erts/emulator/test/mtx_SUITE.erl +++ b/erts/emulator/test/mtx_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2016. All Rights Reserved. +%% Copyright Ericsson AB 2010-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/nested_SUITE.erl b/erts/emulator/test/nested_SUITE.erl index 5059317172..f1b4c03ae4 100644 --- a/erts/emulator/test/nested_SUITE.erl +++ b/erts/emulator/test/nested_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/port_trace_SUITE.erl b/erts/emulator/test/port_trace_SUITE.erl index bfc3c8cb51..c78dc754a9 100644 --- a/erts/emulator/test/port_trace_SUITE.erl +++ b/erts/emulator/test/port_trace_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index b993bf5c69..6ded7ff1c9 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/receive_SUITE.erl b/erts/emulator/test/receive_SUITE.erl index 26eddfd03c..a12019ec83 100644 --- a/erts/emulator/test/receive_SUITE.erl +++ b/erts/emulator/test/receive_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2016. All Rights Reserved. +%% Copyright Ericsson AB 2010-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/signal_SUITE.erl b/erts/emulator/test/signal_SUITE.erl index d788360812..f1d11d1814 100644 --- a/erts/emulator/test/signal_SUITE.erl +++ b/erts/emulator/test/signal_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2016. All Rights Reserved. +%% Copyright Ericsson AB 2006-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/system_profile_SUITE.erl b/erts/emulator/test/system_profile_SUITE.erl index 3a8f862b05..9b678fcff9 100644 --- a/erts/emulator/test/system_profile_SUITE.erl +++ b/erts/emulator/test/system_profile_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2016. All Rights Reserved. +%% Copyright Ericsson AB 2007-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/timer_bif_SUITE.erl b/erts/emulator/test/timer_bif_SUITE.erl index a977eb41c4..fc11a04a31 100644 --- a/erts/emulator/test/timer_bif_SUITE.erl +++ b/erts/emulator/test/timer_bif_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2016. All Rights Reserved. +%% Copyright Ericsson AB 1998-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/trace_SUITE.erl b/erts/emulator/test/trace_SUITE.erl index 9ddc8628b6..72acd33033 100644 --- a/erts/emulator/test/trace_SUITE.erl +++ b/erts/emulator/test/trace_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/trace_bif_SUITE.erl b/erts/emulator/test/trace_bif_SUITE.erl index ce9c60d9d9..f12c359874 100644 --- a/erts/emulator/test/trace_bif_SUITE.erl +++ b/erts/emulator/test/trace_bif_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2016. All Rights Reserved. +%% Copyright Ericsson AB 1998-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/trace_local_SUITE.erl b/erts/emulator/test/trace_local_SUITE.erl index 1cbe6201c3..253d5fed23 100644 --- a/erts/emulator/test/trace_local_SUITE.erl +++ b/erts/emulator/test/trace_local_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2016. All Rights Reserved. +%% Copyright Ericsson AB 2000-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/trace_meta_SUITE.erl b/erts/emulator/test/trace_meta_SUITE.erl index ef58978749..f157a6c9eb 100644 --- a/erts/emulator/test/trace_meta_SUITE.erl +++ b/erts/emulator/test/trace_meta_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2016. All Rights Reserved. +%% Copyright Ericsson AB 2002-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/trace_nif_SUITE.erl b/erts/emulator/test/trace_nif_SUITE.erl index 5c35a8a83f..f796b9d667 100644 --- a/erts/emulator/test/trace_nif_SUITE.erl +++ b/erts/emulator/test/trace_nif_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2016. All Rights Reserved. +%% Copyright Ericsson AB 2010-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/trace_port_SUITE.erl b/erts/emulator/test/trace_port_SUITE.erl index fa6460073a..c85a77536e 100644 --- a/erts/emulator/test/trace_port_SUITE.erl +++ b/erts/emulator/test/trace_port_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/tracer_SUITE.erl b/erts/emulator/test/tracer_SUITE.erl index c2fa3afd9b..ab7d047bc3 100644 --- a/erts/emulator/test/tracer_SUITE.erl +++ b/erts/emulator/test/tracer_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/erts/emulator/test/unique_SUITE.erl b/erts/emulator/test/unique_SUITE.erl index ab02531de3..cfc37bd44f 100644 --- a/erts/emulator/test/unique_SUITE.erl +++ b/erts/emulator/test/unique_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2014-2016. All Rights Reserved. +%% Copyright Ericsson AB 2014-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. -- cgit v1.2.3