File 0937-erts-Fix-seq_trace-token-gc.patch of Package erlang

From 754f0f22dc7221208242c39860dbf2e48022951e Mon Sep 17 00:00:00 2001
From: Lukas Larsson <lukas@erlang.org>
Date: Fri, 5 Feb 2021 18:19:13 +0100
Subject: [PATCH 1/2] erts: Fix seq_trace token gc

If the seq_trace tuple is on the mature side of
the young heap we need to make a copy as otherwise
the tuple will be promited to the old heap before
the token which will lead to all kinds of issues.
---
 erts/emulator/beam/erl_bif_trace.c  |  5 ++++-
 lib/kernel/test/seq_trace_SUITE.erl | 22 ++++++++++++++++++++--
 2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index 7708e0755c..36cad53ce4 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -1841,10 +1841,13 @@ new_seq_trace_token(Process* p, int ensure_new_heap)
 				    make_small(p->seq_trace_lastcnt));
     }
     else if (ensure_new_heap) {
+        Eterm *mature = p->abandoned_heap ? p->abandoned_heap : p->heap;
+        Uint mature_size = p->high_water - mature;
         Eterm* tpl = tuple_val(SEQ_TRACE_TOKEN(p));
         ASSERT(arityval(tpl[0]) == 5);
         if (ErtsInArea(tpl, OLD_HEAP(p),
-                       (OLD_HEND(p) - OLD_HEAP(p))*sizeof(Eterm))) {
+                       (OLD_HEND(p) - OLD_HEAP(p))*sizeof(Eterm)) ||
+            ErtsInArea(tpl, mature, mature_size*sizeof(Eterm))) {
             hp = HAlloc(p, 6);
             sys_memcpy(hp, tpl, 6*sizeof(Eterm));
             SEQ_TRACE_TOKEN(p) = make_tuple(hp);
diff --git a/lib/kernel/test/seq_trace_SUITE.erl b/lib/kernel/test/seq_trace_SUITE.erl
index f8efd1ffea..df1ad00a80 100644
--- a/lib/kernel/test/seq_trace_SUITE.erl
+++ b/lib/kernel/test/seq_trace_SUITE.erl
@@ -26,7 +26,7 @@
 	 init_per_group/2,end_per_group/2,
 	 init_per_testcase/2,end_per_testcase/2]).
 -export([token_set_get/1, tracer_set_get/1, print/1,
-         old_heap_token/1,
+         old_heap_token/1,mature_heap_token/1,
 	 send/1, distributed_send/1, recv/1, distributed_recv/1,
 	 trace_exit/1, distributed_exit/1, call/1, port/1,
 	 match_set_seq_token/1, gc_seq_token/1, label_capability_mismatch/1,
@@ -54,7 +54,7 @@ suite() ->
 all() -> 
     [token_set_get, tracer_set_get, print, send, send_literal,
      distributed_send, recv, distributed_recv, trace_exit,
-     old_heap_token,
+     old_heap_token, mature_heap_token,
      distributed_exit, call, port, match_set_seq_token,
      gc_seq_token, label_capability_mismatch].
 
@@ -971,6 +971,24 @@ old_heap_token(Config) when is_list(Config) ->
     {label,NewLabel} = seq_trace:get_token(label),
     ok.
 
+%% Verify changing label on existing token when it resides on mature heap.
+%% Bug caused faulty ref from old to new heap.
+mature_heap_token(Config) when is_list(Config) ->
+
+    seq_trace:set_token(label, 1),
+    erlang:garbage_collect(self(), [{type, minor}]),
+    %% Now token should be on mature heap
+    %% Set a new non-literal label which should reside on new-heap.
+    NewLabel = {self(), "new label"},
+    seq_trace:set_token(label, NewLabel),
+
+    %% If bug, we now have a ref from mature to new heap. If we now GC
+    %% twice the token will refer to deallocated memory.
+    erlang:garbage_collect(self(), [{type, minor}]),
+    erlang:garbage_collect(self(), [{type, minor}]),
+    {label,NewLabel} = seq_trace:get_token(label),
+    ok.
+
 
 match_set_seq_token(doc) ->
     ["Tests that match spec function set_seq_token does not "
-- 
2.26.2

openSUSE Build Service is sponsored by