aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2017-05-22 17:28:11 +0200
committerLukas Larsson <[email protected]>2017-10-12 17:34:57 +0200
commit19c5a5f7f15d02395694b32090d1b24c3934c5d8 (patch)
tree000235e7e3ee80978a9c20f5a50dd5c344b4c792
parent4c42d5b93e32444f185043e74c9b408cd76dc661 (diff)
downloadotp-19c5a5f7f15d02395694b32090d1b24c3934c5d8.tar.gz
otp-19c5a5f7f15d02395694b32090d1b24c3934c5d8.tar.bz2
otp-19c5a5f7f15d02395694b32090d1b24c3934c5d8.zip
erts: Use SIGRTMIN on linux for sys_suspend
The Linux real-time signal is better used on Linux for suspending schedulers during shutdown as it doesn't collide with SIGUSR2 usage of other applications.
-rw-r--r--erts/emulator/beam/erl_bif_info.c6
-rw-r--r--erts/emulator/beam/sys.h11
-rw-r--r--erts/emulator/test/Makefile1
-rw-r--r--erts/emulator/test/dump_SUITE.erl125
4 files changed, 140 insertions, 3 deletions
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 2ff95a3338..162d179982 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -3699,6 +3699,12 @@ BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1)
Eterm *hp = HAlloc(BIF_P, hsz);
BIF_RET(uword_to_big(size, hp));
}
+ } else if (ERTS_IS_ATOM_STR("scheduler_dump", BIF_ARG_1)) {
+#if defined(ERTS_HAVE_TRY_CATCH) && defined(ERTS_SYS_SUSPEND_SIGNAL)
+ BIF_RET(am_true);
+#else
+ BIF_RET(am_false);
+#endif
}
}
else if (is_tuple(BIF_ARG_1)) {
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index 615f44364b..9dc339053f 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -832,11 +832,16 @@ int erts_sys_unsetenv(char *key);
char *erts_read_env(char *key);
void erts_free_read_env(void *value);
-#if defined(ERTS_THR_HAVE_SIG_FUNCS) && !defined(ETHR_UNUSABLE_SIGUSRX)
+#if defined(ERTS_THR_HAVE_SIG_FUNCS) && \
+ (!defined(ETHR_UNUSABLE_SIGUSRX) || defined(SIGRTMIN))
extern void sys_thr_resume(erts_tid_t tid);
extern void sys_thr_suspend(erts_tid_t tid);
-#define ERTS_SYS_SUSPEND_SIGNAL SIGUSR2
-#endif
+#ifdef SIGRTMIN
+#define ERTS_SYS_SUSPEND_SIGNAL (SIGRTMIN+1)
+#else
+#define ERTS_SYS_SUSPEND_SIGNAL (SIGUSR2)
+#endif /* SIGRTMIN */
+#endif /* HAVE_SIG_FUNCS */
/* utils.c */
diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile
index 370fcb0f3a..5898a8ee8f 100644
--- a/erts/emulator/test/Makefile
+++ b/erts/emulator/test/Makefile
@@ -57,6 +57,7 @@ MODULES= \
dirty_nif_SUITE \
distribution_SUITE \
driver_SUITE \
+ dump_SUITE \
efile_SUITE \
erts_debug_SUITE \
estone_SUITE \
diff --git a/erts/emulator/test/dump_SUITE.erl b/erts/emulator/test/dump_SUITE.erl
new file mode 100644
index 0000000000..38fa198ea6
--- /dev/null
+++ b/erts/emulator/test/dump_SUITE.erl
@@ -0,0 +1,125 @@
+%%
+%% %CopyrightBegin%
+%%
+%% 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.
+%% 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(dump_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+-export([all/0, suite/0, init_per_testcase/2, end_per_testcase/2]).
+
+-export([signal_abort/1]).
+
+-export([load/0]).
+
+-include_lib("kernel/include/file.hrl").
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 2}}].
+
+all() ->
+ [signal_abort].
+
+init_per_testcase(signal_abort, Config) ->
+ SO = erlang:system_info(schedulers_online),
+ erts_debug:set_internal_state(available_internal_state, true),
+ Dump = erts_debug:get_internal_state(scheduler_dump),
+ erts_debug:set_internal_state(available_internal_state, false),
+ if SO < 3 ->
+ {skip, "not enough schedulers"};
+ not Dump ->
+ {skip, "the platform does not support scheduler dump"};
+ Dump ->
+ Config
+ end.
+
+end_per_testcase(_, Config) ->
+ Config.
+
+%%%
+%%% The test cases -------------------------------------------------------------
+%%%
+
+%% Test that a snapshot is taken of other schedulers using a signal
+%% when a crash dump is generated.
+signal_abort(Config) ->
+
+ Dump = filename:join(proplists:get_value(priv_dir, Config),"signal_abort.dump"),
+
+ {ok, Node} = start_node(Config),
+
+ _P1 = spawn(Node, ?MODULE, load, []),
+ _P2 = spawn(Node, ?MODULE, load, []),
+ _P3 = spawn(Node, ?MODULE, load, []),
+ _P4 = spawn(Node, ?MODULE, load, []),
+ _P5 = spawn(Node, ?MODULE, load, []),
+ _P6 = spawn(Node, ?MODULE, load, []),
+
+ timer:sleep(500),
+
+ true = rpc:call(Node, os, putenv, ["ERL_CRASH_DUMP",Dump]),
+ rpc:call(Node, erlang, halt, ["dump"]),
+
+ {ok, Bin} = get_dump_when_done(Dump),
+
+ ct:log("~s",[Bin]),
+
+ {match, Matches} = re:run(Bin,"Current Process: <",[global]),
+
+ ct:log("Found ~p",[Matches]),
+
+ true = length(Matches) > 1,
+
+ file:delete(Dump),
+
+ ok.
+
+get_dump_when_done(Dump) ->
+ case file:read_file_info(Dump) of
+ {ok, #file_info{ size = Sz }} ->
+ get_dump_when_done(Dump, Sz);
+ {error, enoent} ->
+ timer:sleep(100),
+ get_dump_when_done(Dump)
+ end.
+
+get_dump_when_done(Dump, Sz) ->
+ timer:sleep(100),
+ case file:read_file_info(Dump) of
+ {ok, #file_info{ size = Sz }} ->
+ file:read_file(Dump);
+ {ok, #file_info{ size = NewSz }} ->
+ get_dump_when_done(Dump, NewSz)
+ end.
+
+load() ->
+ lists:seq(1,10000),
+ load().
+
+start_node(Config) 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}]).