aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/test/match_spec_SUITE.erl61
-rw-r--r--lib/stdlib/test/ets_SUITE.erl57
2 files changed, 110 insertions, 8 deletions
diff --git a/erts/emulator/test/match_spec_SUITE.erl b/erts/emulator/test/match_spec_SUITE.erl
index 2b21fa58f4..461773114e 100644
--- a/erts/emulator/test/match_spec_SUITE.erl
+++ b/erts/emulator/test/match_spec_SUITE.erl
@@ -27,8 +27,9 @@
destructive_in_test_bif/1, guard_exceptions/1,
unary_plus/1, unary_minus/1, moving_labels/1]).
-export([fpe/1]).
+-export([otp_9422/1]).
--export([runner/2]).
+-export([runner/2, loop_runner/3]).
-export([f1/1, f2/2, f3/2, fn/1, fn/2, fn/3]).
-export([do_boxed_and_small/0]).
@@ -57,7 +58,8 @@ all() ->
trace_control_word, silent, silent_no_ms, ms_trace2,
ms_trace3, boxed_and_small, destructive_in_test_bif,
guard_exceptions, unary_plus, unary_minus, fpe,
- moving_labels];
+ moving_labels,
+ otp_9422];
true -> [not_run]
end.
@@ -208,6 +210,43 @@ test_3(Config) when is_list(Config) ->
?line collect(P1, [{trace, P1, call, {?MODULE, f2, [a, b]}, [true]}]),
?line ok.
+otp_9422(doc) -> [];
+otp_9422(Config) when is_list(Config) ->
+ Laps = 1000,
+ ?line Fun1 = fun() -> otp_9422_tracee() end,
+ ?line P1 = spawn_link(?MODULE, loop_runner, [self(), Fun1, Laps]),
+ io:format("spawned ~p as tracee\n", [P1]),
+
+ ?line erlang:trace(P1, true, [call, silent]),
+
+ ?line Fun2 = fun() -> otp_9422_trace_changer() end,
+ ?line P2 = spawn_link(?MODULE, loop_runner, [self(), Fun2, Laps]),
+ io:format("spawned ~p as trace_changer\n", [P2]),
+
+ start_collect(P1),
+ start_collect(P2),
+
+ %%receive after 10*1000 -> ok end,
+
+ stop_collect(P1),
+ stop_collect(P2),
+ ok.
+
+otp_9422_tracee() ->
+ ?MODULE:f1(a),
+ ?MODULE:f1(b),
+ ?MODULE:f1(c).
+
+otp_9422_trace_changer() ->
+ Pat1 = [{[a], [], [{enable_trace, arity}]}],
+ ?line erlang:trace_pattern({?MODULE, f1, 1}, Pat1),
+ Pat2 = [{[b], [], [{disable_trace, arity}]}],
+ ?line erlang:trace_pattern({?MODULE, f1, 1}, Pat2).
+
+
+
+
+
bad_match_spec_bin(Config) when is_list(Config) ->
{'EXIT',{badarg,_}} = (catch ets:match_spec_run([1], <<>>)),
B0 = <<1,2>>,
@@ -932,6 +971,24 @@ runner(Collector, Fun) ->
Collector ! {gone, self()}
end.
+loop_runner(Collector, Fun, Laps) ->
+ receive
+ {go, Collector} ->
+ go
+ end,
+ loop_runner_cont(Collector, Fun, 0, Laps).
+
+loop_runner_cont(_Collector, _Fun, Laps, Laps) ->
+ receive
+ {done, Collector} ->
+ io:format("loop_runner ~p exit after ~p laps\n", [self(), Laps]),
+ Collector ! {gone, self()}
+ end;
+loop_runner_cont(Collector, Fun, N, Laps) ->
+ Fun(),
+ loop_runner_cont(Collector, Fun, N+1, Laps).
+
+
f1(X) ->
{X}.
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index c9d82ec5f5..9341300f90 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -72,6 +72,7 @@
exit_many_many_tables_owner/1]).
-export([write_concurrency/1, heir/1, give_away/1, setopts/1]).
-export([bad_table/1, types/1]).
+-export([otp_9423/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
%% Convenience for manual testing
@@ -143,7 +144,8 @@ all() ->
otp_8166, exit_large_table_owner,
exit_many_large_table_owner, exit_many_tables_owner,
exit_many_many_tables_owner, write_concurrency, heir,
- give_away, setopts, bad_table, types].
+ give_away, setopts, bad_table, types,
+ otp_9423].
groups() ->
[{new, [],
@@ -5420,7 +5422,39 @@ types_do(Opts) ->
?line verify_etsmem(EtsMem).
-
+otp_9423(doc) -> ["vm-deadlock caused by race between ets:delete and others on write_concurrency table"];
+otp_9423(Config) when is_list(Config) ->
+ InitF = fun(_) -> {0,0} end,
+ ExecF = fun({S,F}) ->
+ receive
+ stop ->
+ io:format("~p got stop\n", [self()]),
+ [end_of_work | {"Succeded=",S,"Failed=",F}]
+ after 0 ->
+ %%io:format("~p (~p) doing lookup\n", [self(), {S,F}]),
+ try ets:lookup(otp_9423, key) of
+ [] -> {S+1,F}
+ catch
+ error:badarg -> {S,F+1}
+ end
+ end
+ end,
+ FiniF = fun(R) -> R end,
+ case run_workers(InitF, ExecF, FiniF, infinite, 1) of
+ Pids when is_list(Pids) ->
+ %%[P ! start || P <- Pids],
+ repeat(fun() -> ets:new(otp_9423, [named_table, public, {write_concurrency,true}]),
+ ets:delete(otp_9423)
+ end, 10000),
+ [P ! stop || P <- Pids],
+ wait_pids(Pids),
+ ok;
+
+ Skipped -> Skipped
+ end.
+
+
+
%
% Utility functions:
@@ -5434,21 +5468,30 @@ add_lists([E1|T1], [E2|T2], Acc) ->
add_lists(T1, T2, [E1+E2 | Acc]).
run_workers(InitF,ExecF,FiniF,Laps) ->
+ run_workers(InitF,ExecF,FiniF,Laps, 0).
+run_workers(InitF,ExecF,FiniF,Laps, Exclude) ->
case erlang:system_info(smp_support) of
true ->
- run_workers_do(InitF,ExecF,FiniF,Laps);
+ run_workers_do(InitF,ExecF,FiniF,Laps, Exclude);
false ->
{skipped,"No smp support"}
end.
-
+
run_workers_do(InitF,ExecF,FiniF,Laps) ->
- NumOfProcs = erlang:system_info(schedulers),
+ run_workers_do(InitF,ExecF,FiniF,Laps, 0).
+run_workers_do(InitF,ExecF,FiniF,Laps, Exclude) ->
+ ?line NumOfProcs = case erlang:system_info(schedulers) of
+ N when (N > Exclude) -> N - Exclude
+ end,
io:format("smp starting ~p workers\n",[NumOfProcs]),
Seeds = [{ProcN,random:uniform(9999)} || ProcN <- lists:seq(1,NumOfProcs)],
Parent = self(),
Pids = [spawn_link(fun()-> worker(Seed,InitF,ExecF,FiniF,Laps,Parent,NumOfProcs) end)
|| Seed <- Seeds],
- wait_pids(Pids).
+ case Laps of
+ infinite -> Pids;
+ _ -> wait_pids(Pids)
+ end.
worker({ProcN,Seed}, InitF, ExecF, FiniF, Laps, Parent, NumOfProcs) ->
io:format("smp worker ~p, seed=~p~n",[self(),Seed]),
@@ -5463,6 +5506,8 @@ worker_loop(0, _, State) ->
State;
worker_loop(_, _, [end_of_work|State]) ->
State;
+worker_loop(infinite, ExecF, State) ->
+ worker_loop(infinite,ExecF,ExecF(State));
worker_loop(N, ExecF, State) ->
worker_loop(N-1,ExecF,ExecF(State)).