aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/test
diff options
context:
space:
mode:
authorDan Gudmundsson <[email protected]>2014-02-18 17:21:55 +0100
committerDan Gudmundsson <[email protected]>2014-02-19 15:32:19 +0100
commit397e69fa95457f9660831ba1e551c784eb61e93e (patch)
tree4a77b0bc80de8adfd3ec9e70b08c276220cafacb /lib/kernel/test
parent6c9002f9174d40b69b3a5bcd5ef219ce4ceb3622 (diff)
downloadotp-397e69fa95457f9660831ba1e551c784eb61e93e.tar.gz
otp-397e69fa95457f9660831ba1e551c784eb61e93e.tar.bz2
otp-397e69fa95457f9660831ba1e551c784eb61e93e.zip
kernel: Fix an application terminate deadlock possibility
Could happen if get_child was called during terminate. io (since it is a group_leader) also causes problems after get_child was called. Split up and do it async.
Diffstat (limited to 'lib/kernel/test')
-rw-r--r--lib/kernel/test/application_SUITE.erl33
-rw-r--r--lib/kernel/test/application_SUITE_data/deadlock/deadlock.app2
-rw-r--r--lib/kernel/test/application_SUITE_data/deadlock/deadlock.erl12
3 files changed, 41 insertions, 6 deletions
diff --git a/lib/kernel/test/application_SUITE.erl b/lib/kernel/test/application_SUITE.erl
index ff62297f2d..ccb3760309 100644
--- a/lib/kernel/test/application_SUITE.erl
+++ b/lib/kernel/test/application_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2014. 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
@@ -36,7 +36,7 @@
-export([config_change/1, persistent_env/1,
distr_changed_tc1/1, distr_changed_tc2/1,
ensure_started/1, ensure_all_started/1,
- shutdown_func/1, do_shutdown/1, shutdown_timeout/1]).
+ shutdown_func/1, do_shutdown/1, shutdown_timeout/1, shutdown_deadlock/1]).
-define(TESTCASE, testcase_name).
-define(testcase, ?config(?TESTCASE, Config)).
@@ -54,6 +54,7 @@ all() ->
script_start, nodedown_start, permit_false_start_local,
permit_false_start_dist, get_key, get_env, ensure_all_started,
{group, distr_changed}, config_change, shutdown_func, shutdown_timeout,
+ shutdown_deadlock,
persistent_env].
groups() ->
@@ -961,7 +962,7 @@ nodedown_start(Conf) when is_list(Conf) ->
ensure_started(suite) -> [];
ensure_started(doc) -> ["Test application:ensure_started/1."];
-ensure_started(Conf) ->
+ensure_started(_Conf) ->
{ok, Fd} = file:open("app1.app", [write]),
w_app1(Fd),
@@ -981,7 +982,7 @@ ensure_started(Conf) ->
ensure_all_started(suite) -> [];
ensure_all_started(doc) -> ["Test application:ensure_all_started/1-2."];
-ensure_all_started(Conf) ->
+ensure_all_started(_Conf) ->
{ok, Fd1} = file:open("app1.app", [write]),
w_app1(Fd1),
@@ -2096,7 +2097,31 @@ shutdown_timeout(Config) when is_list(Config) ->
end,
ok.
+%%%-----------------------------------------------------------------
+%%% Provokes a (previous) application shutdown deadlock
+%%%-----------------------------------------------------------------
+shutdown_deadlock(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir,Config),
+ code:add_path(filename:join([DataDir,deadlock])),
+ %% ok = rpc:call(Cp1, application, start, [sasl]),
+ ok = application:start(deadlock),
+ Tester = self(),
+ application:set_env(deadlock, fail_stop, Tester),
+ spawn(fun() -> Tester ! {stop, application:stop(deadlock)} end),
+ receive
+ {deadlock, Server} ->
+ spawn(fun() ->
+ Master = application_controller:get_master(deadlock),
+ Child = application_master:get_child(Master),
+ Tester ! {child, Child}
+ end),
+ timer:sleep(100),
+ erlang:display({self(), "Sending Continue", Server}),
+ Server ! continue
+ end,
+ [_|_] = application:which_applications(),
+ ok.
%%-----------------------------------------------------------------
diff --git a/lib/kernel/test/application_SUITE_data/deadlock/deadlock.app b/lib/kernel/test/application_SUITE_data/deadlock/deadlock.app
index 0c1001bed6..233c7a3f76 100644
--- a/lib/kernel/test/application_SUITE_data/deadlock/deadlock.app
+++ b/lib/kernel/test/application_SUITE_data/deadlock/deadlock.app
@@ -4,5 +4,5 @@
{applications, [kernel, stdlib, sasl]},
{modules, [deadlock]},
{mod, {deadlock, []}},
- {env, [{fail_start, false}]}
+ {env, [{fail_start, false}, {fail_stop, false}]}
]}.
diff --git a/lib/kernel/test/application_SUITE_data/deadlock/deadlock.erl b/lib/kernel/test/application_SUITE_data/deadlock/deadlock.erl
index 5f68bf9078..3ef6105371 100644
--- a/lib/kernel/test/application_SUITE_data/deadlock/deadlock.erl
+++ b/lib/kernel/test/application_SUITE_data/deadlock/deadlock.erl
@@ -21,7 +21,7 @@ init([sup]) ->
{ok, {{one_for_one, 5, 10}, [
{
sasl_syslog_dm, {?MODULE, start_link, []},
- permanent, brutal_kill, worker,
+ permanent, 25000, worker,
[deadlock]
}
]}};
@@ -32,6 +32,8 @@ init([sup]) ->
init([child]) ->
case application:get_env(deadlock, fail_start) of
{ok, false} ->
+ process_flag(trap_exit, true),
+ io:format("~p: Traps exit~n",[?MODULE]),
%% we must not fail on the first init, otherwise supervisor
%% terminates immediately
{ok, []};
@@ -50,6 +52,14 @@ handle_info(_Msg, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
+ case application:get_env(deadlock, fail_stop) of
+ {ok, false} -> ok;
+ {ok, Tester} ->
+ Tester ! {deadlock, self()},
+ io:format("~p: Waiting in terminate (~p)~n",[?MODULE,Tester]),
+ receive continue -> ok end
+ end,
+ io:format("~p: terminates~n", [?MODULE]),
ok.
code_change(_OldVsn, State, _Extra) ->