File 5551-erts-Fix-crash-dump-assert-when-heart-is-set.patch of Package erlang
From 8637f8395819caaffd14614a403da207e3be6b39 Mon Sep 17 00:00:00 2001
From: Lukas Larsson <lukas@erlang.org>
Date: Tue, 22 Mar 2022 10:14:00 +0100
Subject: [PATCH] erts: Fix crash dump assert when heart is set
If a crash dump was generated while the VM was supervised
with heart, the debug build would assert because the heart
port was flushed.
This commit moves where erts_is_crash_dumping is set so that
the heart flush works as it should.
More importantly (perhaps) the commit also moves the
erts_thr_progress_fatal_error_block to be earlier so
that multiple threads do not race to create the crash dump.
The thr progress block was incorrectly moved by 63e1d64 when
fixing a problem with suspension of schedulers.
---
erts/emulator/beam/break.c | 18 ++++++++---------
erts/emulator/beam/erl_thr_progress.c | 2 +-
erts/emulator/test/dump_SUITE.erl | 29 ++++++++++++++++++++++++---
3 files changed, 36 insertions(+), 13 deletions(-)
diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c
index 530dee0746..fa2f77dc7c 100644
--- a/erts/emulator/beam/break.c
+++ b/erts/emulator/beam/break.c
@@ -789,6 +789,15 @@ erl_crash_dump_v(char *file, int line, const char* fmt, va_list args)
if (ERTS_SOMEONE_IS_CRASH_DUMPING)
return;
+ /* Order all managed threads to block, this has to be done
+ first to guarantee that this is the only thread to generate
+ crash dump. */
+ erts_thr_progress_fatal_error_block(&tpd_buf);
+
+ /* Allow us to pass certain places without locking... */
+ erts_atomic32_set_mb(&erts_writing_erl_crash_dump, 1);
+ erts_tsd_set(erts_is_crash_dumping_key, (void *) 1);
+
envsz = sizeof(env);
/* ERL_CRASH_DUMP_SECONDS not set
* if we have a heart port, break immediately
@@ -886,11 +895,6 @@ erl_crash_dump_v(char *file, int line, const char* fmt, va_list args)
time(&now);
erts_cbprintf(to, to_arg, "=erl_crash_dump:0.5\n%s", ctime(&now));
- /* Order all managed threads to block, this has to be done
- first to guarantee that this is the only thread to generate
- crash dump. */
- erts_thr_progress_fatal_error_block(&tpd_buf);
-
#ifdef ERTS_SYS_SUSPEND_SIGNAL
/*
* We suspend all scheduler threads so that we can dump some
@@ -912,10 +916,6 @@ erl_crash_dump_v(char *file, int line, const char* fmt, va_list args)
#endif
- /* Allow us to pass certain places without locking... */
- erts_atomic32_set_mb(&erts_writing_erl_crash_dump, 1);
- erts_tsd_set(erts_is_crash_dumping_key, (void *) 1);
-
if (file != NULL)
erts_cbprintf(to, to_arg, "The error occurred in file %s, line %d\n", file, line);
diff --git a/erts/emulator/beam/erl_thr_progress.c b/erts/emulator/beam/erl_thr_progress.c
index 1929cee6d2..1faf8a7a0f 100644
--- a/erts/emulator/beam/erl_thr_progress.c
+++ b/erts/emulator/beam/erl_thr_progress.c
@@ -1369,7 +1369,7 @@ erts_thr_progress_fatal_error_block(ErtsThrPrgrData *tmp_tpd_bufp)
init_tmp_thr_prgr_data(tpd);
}
- /* Returns number of threads that have not yes been blocked */
+ /* Returns number of threads that have not yet been blocked */
return thr_progress_block(tpd, 0);
}
diff --git a/erts/emulator/test/dump_SUITE.erl b/erts/emulator/test/dump_SUITE.erl
index ec451fd35b..150f7331b9 100644
--- a/erts/emulator/test/dump_SUITE.erl
+++ b/erts/emulator/test/dump_SUITE.erl
@@ -24,7 +24,8 @@
-export([all/0, suite/0, init_per_testcase/2, end_per_testcase/2]).
--export([signal_abort/1]).
+-export([signal_abort/1,
+ heart_dump/1, heart_no_dump/1]).
-export([load/1]).
@@ -35,7 +36,7 @@ suite() ->
{timetrap, {minutes, 2}}].
all() ->
- [signal_abort].
+ [signal_abort, heart_dump, heart_no_dump].
init_per_testcase(signal_abort, Config) ->
SO = erlang:system_info(schedulers_online),
@@ -212,6 +213,27 @@ free_dump(Config) when is_list(Config) ->
ok.
+%% Test that crash dumping works when heart is used
+heart_dump(Config) ->
+ Dump = filename:join(proplists:get_value(priv_dir, Config),"heart.dump"),
+ {ok, Node} = start_node(Config,"-heart"),
+ true = rpc:call(Node, os, putenv, ["ERL_CRASH_DUMP",Dump]),
+ true = rpc:call(Node, os, putenv, ["ERL_CRASH_DUMP_SECONDS","10"]),
+ rpc:call(Node, erlang, halt, ["dump"]),
+ {ok, _Bin} = get_dump_when_done(Dump),
+ ok.
+
+%% Test that there is no crash dump if heart is used and DUMP_SECONDS is not set
+heart_no_dump(Config) ->
+ Dump = filename:join(proplists:get_value(priv_dir, Config),"heart_no.dump"),
+ {ok, Node} = start_node(Config,"-heart"),
+ true = rpc:call(Node, os, putenv, ["ERL_CRASH_DUMP",Dump]),
+ true = rpc:call(Node, os, unsetenv, ["ERL_CRASH_DUMP_SECONDS"]),
+ rpc:call(Node, erlang, halt, ["dump"]),
+ timer:sleep(1000),
+ {error, enoent} = file:read_file_info(Dump),
+ ok.
+
get_dump_when_done(Dump) ->
case file:read_file_info(Dump) of
{ok, #file_info{ size = Sz }} ->
@@ -234,6 +255,8 @@ get_dump_when_done(Dump, Sz) ->
load().
start_node(Config) when is_list(Config) ->
+ start_node(Config, "").
+start_node(Config, Extra) when is_list(Config) ->
Pa = filename:dirname(code:which(?MODULE)),
Name = list_to_atom(atom_to_list(?MODULE)
++ "-"
@@ -242,4 +265,4 @@ start_node(Config) when is_list(Config) ->
++ integer_to_list(erlang:system_time(second))
++ "-"
++ integer_to_list(erlang:unique_integer([positive]))),
- test_server:start_node(Name, slave, [{args, "-pa "++Pa}]).
+ test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Extra}]).
--
2.34.1