From 45a4a46333b1e8e6f66ba923deaf947a67ae7737 Mon Sep 17 00:00:00 2001 From: Simon Cornish <7t9jna402@sneakemail.com> Date: Mon, 25 Apr 2016 22:21:07 -0700 Subject: Don't kill old erlang if HEART_NO_KILL is set If the environment variable HEART_NO_KILL is set then heart won't kill the old erlang process. This is desirable if the command executed by heart takes care of this. --- erts/etc/common/heart.c | 9 +++++++++ lib/kernel/doc/src/heart.xml | 10 ++++++++++ lib/kernel/test/heart_SUITE.erl | 40 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/erts/etc/common/heart.c b/erts/etc/common/heart.c index 1a826221fb..b6fbfd075c 100644 --- a/erts/etc/common/heart.c +++ b/erts/etc/common/heart.c @@ -119,6 +119,8 @@ #define HEART_COMMAND_ENV "HEART_COMMAND" #define ERL_CRASH_DUMP_SECONDS_ENV "ERL_CRASH_DUMP_SECONDS" #define HEART_KILL_SIGNAL "HEART_KILL_SIGNAL" +#define HEART_NO_KILL "HEART_NO_KILL" + #define MSG_HDR_SIZE (2) #define MSG_HDR_PLUS_OP_SIZE (3) @@ -524,6 +526,10 @@ static void kill_old_erlang(void){ HANDLE erlh; DWORD exit_code; + + if (is_env_set(HEART_NO_KILL)) + return; + if(heart_beat_kill_pid != 0){ if((erlh = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE | @@ -557,6 +563,9 @@ kill_old_erlang(void){ int sig = SIGKILL; char *sigenv = NULL; + if (is_env_set(HEART_NO_KILL)) + return; + sigenv = get_env(HEART_KILL_SIGNAL); if (sigenv && strcmp(sigenv, "SIGABRT") == 0) { print_error("kill signal SIGABRT requested"); diff --git a/lib/kernel/doc/src/heart.xml b/lib/kernel/doc/src/heart.xml index 9da4773f2d..bfb4ce45e6 100644 --- a/lib/kernel/doc/src/heart.xml +++ b/lib/kernel/doc/src/heart.xml @@ -89,6 +89,16 @@
 % erl -heart -env HEART_KILL_SIGNAL SIGABRT ...
+

If heart should not kill the Erlang runtime system, this can be indicated + using the environment variable . + This can be useful if the command executed by heart takes care of this, + for example as part of a specific cleanup sequence. + If unset, the default behaviour will be to kill as described above. +

+ +
+% erl -heart -env HEART_NO_KILL 1 ...
+

Furthermore, has the following behaviour on heart: diff --git a/lib/kernel/test/heart_SUITE.erl b/lib/kernel/test/heart_SUITE.erl index 39cd29cea0..a848bc78f7 100644 --- a/lib/kernel/test/heart_SUITE.erl +++ b/lib/kernel/test/heart_SUITE.erl @@ -29,11 +29,11 @@ set_cmd/1, clear_cmd/1, get_cmd/1, callback_api/1, options_api/1, - dont_drop/1, kill_pid/1]). + dont_drop/1, kill_pid/1, heart_no_kill/1]). -export([init_per_testcase/2, end_per_testcase/2]). --export([start_heart_stress/1, mangle/1, suicide_by_heart/0]). +-export([start_heart_stress/1, mangle/1, suicide_by_heart/0, non_suicide_by_heart/0]). -define(DEFAULT_TIMEOUT_SECS, 120). @@ -507,6 +507,30 @@ do_kill_pid(_Config) -> false end. + +heart_no_kill(suite) -> + []; +heart_no_kill(doc) -> + ["Tests that heart doesn't kill the old erlang node when ", + "HEART_NO_KILL is set."]; +heart_no_kill(Config) when is_list(Config) -> + ok = do_no_kill(Config). + +do_no_kill(_Config) -> + Name = heart_test, + {ok,Node} = start_node_run(Name,[],non_suicide_by_heart,[]), + io:format("Node is ~p~n", [Node]), + ok = wait_for_node(Node,15), + io:format("wait_for_node is ~p~n", [ok]), + erlang:monitor_node(Node, true), + receive {nodedown,Node} -> false + after 30000 -> + io:format("Node didn't die..\n"), + rpc:call(Node,init,stop,[]), + io:format("done init:stop..\n"), + ok + end. + wait_for_node(_,0) -> false; wait_for_node(Node,N) -> @@ -625,6 +649,18 @@ suicide_by_heart() -> sallad end. +non_suicide_by_heart() -> + P = open_port({spawn,"heart -ht 11 -pid "++os:getpid()},[exit_status, {env, {"HEART_NO_KILL", "1"}}, {packet,2}]), + receive X -> X end, + %% Just hang and wait for heart to timeout + receive + {P,{exit_status,_}} -> + ok + after + 20000 -> + exit(timeout) + end. + %% generate a module from binary generate(Module, Attributes, FunStrings) -> -- cgit v1.2.3 From 85996c92853e90cb233a1405b1c8c7bb1b8ca54e Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 3 Jun 2016 11:43:47 +0200 Subject: erts: make HEART_NO_KILL have to be set to TRUE --- erts/etc/common/heart.c | 13 ++++++++----- lib/kernel/doc/src/heart.xml | 5 +++-- lib/kernel/test/heart_SUITE.erl | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/erts/etc/common/heart.c b/erts/etc/common/heart.c index b6fbfd075c..0dd82cc036 100644 --- a/erts/etc/common/heart.c +++ b/erts/etc/common/heart.c @@ -526,8 +526,10 @@ static void kill_old_erlang(void){ HANDLE erlh; DWORD exit_code; + char* envvar = NULL; - if (is_env_set(HEART_NO_KILL)) + envvar = get_env(HEART_NO_KILL); + if (!envvar || strcmp(envvar, "TRUE") == 0) return; if(heart_beat_kill_pid != 0){ @@ -561,13 +563,14 @@ kill_old_erlang(void){ pid_t pid; int i, res; int sig = SIGKILL; - char *sigenv = NULL; + char *envvar = NULL; - if (is_env_set(HEART_NO_KILL)) + envvar = get_env(HEART_NO_KILL); + if (!envvar || strcmp(envvar, "TRUE") == 0) return; - sigenv = get_env(HEART_KILL_SIGNAL); - if (sigenv && strcmp(sigenv, "SIGABRT") == 0) { + envvar = get_env(HEART_KILL_SIGNAL); + if (envvar && strcmp(envvar, "SIGABRT") == 0) { print_error("kill signal SIGABRT requested"); sig = SIGABRT; } diff --git a/lib/kernel/doc/src/heart.xml b/lib/kernel/doc/src/heart.xml index bfb4ce45e6..1ad6a04b75 100644 --- a/lib/kernel/doc/src/heart.xml +++ b/lib/kernel/doc/src/heart.xml @@ -90,10 +90,11 @@ % erl -heart -env HEART_KILL_SIGNAL SIGABRT ...

If heart should not kill the Erlang runtime system, this can be indicated - using the environment variable . + using the environment variable . This can be useful if the command executed by heart takes care of this, for example as part of a specific cleanup sequence. - If unset, the default behaviour will be to kill as described above. + If unset, or not set to , the default behaviour + will be to kill as described above.

diff --git a/lib/kernel/test/heart_SUITE.erl b/lib/kernel/test/heart_SUITE.erl
index a848bc78f7..16b9f7a9ee 100644
--- a/lib/kernel/test/heart_SUITE.erl
+++ b/lib/kernel/test/heart_SUITE.erl
@@ -650,7 +650,7 @@ suicide_by_heart() ->
     end.
 
 non_suicide_by_heart() ->
-    P = open_port({spawn,"heart -ht 11 -pid "++os:getpid()},[exit_status, {env, {"HEART_NO_KILL", "1"}}, {packet,2}]),
+    P = open_port({spawn,"heart -ht 11 -pid "++os:getpid()},[exit_status, {env, {"HEART_NO_KILL", "TRUE"}}, {packet,2}]),
     receive X -> X end,
     %% Just hang and wait for heart to timeout
     receive
-- 
cgit v1.2.3