aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator
diff options
context:
space:
mode:
authorSteve Vinoski <[email protected]>2016-01-28 16:37:33 -0500
committerRickard Green <[email protected]>2016-02-15 09:55:42 +0100
commit57cff1f4286a9511926ee37c015b3f6f081d64d0 (patch)
tree437d8a0d33d99dded188f977d942d5e2563464bd /erts/emulator
parenta7f48d4972be0c7984d5cb0e08e73260c0fdbe1b (diff)
downloadotp-57cff1f4286a9511926ee37c015b3f6f081d64d0.tar.gz
otp-57cff1f4286a9511926ee37c015b3f6f081d64d0.tar.bz2
otp-57cff1f4286a9511926ee37c015b3f6f081d64d0.zip
Add dirty scheduler process termination test
In scheduler_SUITE add a new test that runs a single dirty I/O scheduler and launches a number of dirty I/O NIF calls that each sleep for 3 seconds. Given the single scheduler, the first of these will run while the rest queue up. Then start killing these processes, and verify they call exit correctly.
Diffstat (limited to 'erts/emulator')
-rw-r--r--erts/emulator/test/scheduler_SUITE.erl50
-rw-r--r--erts/emulator/test/scheduler_SUITE_data/Makefile.src8
-rw-r--r--erts/emulator/test/scheduler_SUITE_data/scheduler_SUITE.c31
3 files changed, 88 insertions, 1 deletions
diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl
index 986a73ebb1..684e8a3b4e 100644
--- a/erts/emulator/test/scheduler_SUITE.erl
+++ b/erts/emulator/test/scheduler_SUITE.erl
@@ -56,6 +56,7 @@
scheduler_threads/1,
scheduler_suspend/1,
dirty_scheduler_threads/1,
+ dirty_scheduler_exit/1,
reader_groups/1]).
-define(DEFAULT_TIMEOUT, ?t:minutes(15)).
@@ -70,7 +71,7 @@ all() ->
equal_and_high_with_part_time_max, equal_with_high,
equal_with_high_max, bound_process,
{group, scheduler_bind}, scheduler_threads, scheduler_suspend,
- dirty_scheduler_threads,
+ dirty_scheduler_threads, dirty_scheduler_exit,
reader_groups].
groups() ->
@@ -1166,6 +1167,53 @@ get_dsstate(Config, Cmd) ->
stop_node(Node),
{DSCPU, DSCPUOnln, DSIO}.
+dirty_scheduler_exit(Config) when is_list(Config) ->
+ try
+ erlang:system_info(dirty_cpu_schedulers),
+ dirty_scheduler_exit_test(Config)
+ catch
+ error:badarg ->
+ {skipped, "No dirty scheduler support"}
+ end.
+
+dirty_scheduler_exit_test(Config) ->
+ {ok, Node} = start_node(Config, "+SDio 1"),
+ [ok] = mcall(Node,
+ [fun() ->
+ Path = ?config(data_dir, Config),
+ Lib = atom_to_list(?MODULE),
+ ok = erlang:load_nif(filename:join(Path,Lib), []),
+ ok = test_dirty_scheduler_exit()
+ 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 dirty_sleeper/0),
+ 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,killed} ->
+ ok
+ end,
+ wait_dse(Pids).
+
+dirty_sleeper() ->
+ erlang:nif_error({error,?MODULE}).
+
scheduler_suspend(Config) when is_list(Config) ->
?line Dog = ?t:timetrap(?t:minutes(5)),
?line lists:foreach(fun (S) -> scheduler_suspend_test(Config, S) end,
diff --git a/erts/emulator/test/scheduler_SUITE_data/Makefile.src b/erts/emulator/test/scheduler_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..859112cf19
--- /dev/null
+++ b/erts/emulator/test/scheduler_SUITE_data/Makefile.src
@@ -0,0 +1,8 @@
+
+SCHEDULER_LIBS = scheduler_SUITE@dll@
+
+all: $(SCHEDULER_LIBS)
+
+@SHLIB_RULES@
+
+$(SCHEDULER_LIBS): scheduler_SUITE.c
diff --git a/erts/emulator/test/scheduler_SUITE_data/scheduler_SUITE.c b/erts/emulator/test/scheduler_SUITE_data/scheduler_SUITE.c
new file mode 100644
index 0000000000..022858c114
--- /dev/null
+++ b/erts/emulator/test/scheduler_SUITE_data/scheduler_SUITE.c
@@ -0,0 +1,31 @@
+#include <unistd.h>
+#include "erl_nif.h"
+
+static int
+load(ErlNifEnv* env, void** priv, ERL_NIF_TERM info)
+{
+ ErlNifSysInfo sys_info;
+ enif_system_info(&sys_info, sizeof(ErlNifSysInfo));
+ if (!sys_info.smp_support || !sys_info.dirty_scheduler_support)
+ return 1;
+ return 0;
+}
+
+static ERL_NIF_TERM
+dirty_sleeper(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+#ifdef ERL_NIF_DIRTY_SCHEDULER_SUPPORT
+ sleep(3);
+#endif
+ return enif_make_atom(env, "ok");
+}
+
+static ErlNifFunc funcs[] = {
+#ifdef ERL_NIF_DIRTY_SCHEDULER_SUPPORT
+ {"dirty_sleeper", 0, dirty_sleeper, ERL_NIF_DIRTY_JOB_IO_BOUND}
+#else
+ {"dirty_sleeper", 0, dirty_sleeper, 0}
+#endif
+};
+
+ERL_NIF_INIT(scheduler_SUITE, funcs, &load, NULL, NULL, NULL);