File 0515-erts-Fix-bug-in-ets-delete_all_objects.patch of Package erlang

From c9f7575e9f92ccd49a73e5f39eba3e847227eb83 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson <sverker@erlang.org>
Date: Tue, 11 Oct 2022 18:42:53 +0200
Subject: [PATCH 1/2] erts: Fix bug in ets:delete_all_objects

This bug does not seem to cause any problem in practice
other than the debug ASSERT(fixdel->all) in the same function.
---
 erts/emulator/beam/erl_db_hash.c |  2 +-
 erts/emulator/beam/erl_db_hash.h |  5 ++-
 lib/stdlib/test/ets_SUITE.erl    | 61 +++++++++++++++++++++++++++++++-
 3 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c
index 6eb7bde1b4..716b3a0485 100644
--- a/erts/emulator/beam/erl_db_hash.c
+++ b/erts/emulator/beam/erl_db_hash.c
@@ -2728,7 +2728,7 @@ static SWord db_mark_all_deleted_hash(DbTable *tbl, SWord reds)
     if (i < NACTIVE(tb)) {
          /* Yield */
         fixdel->slot = i;
-        fixdel->all = 0;
+        fixdel->all = 1;
         fixdel->trap = 1;
         return -1;
     }
diff --git a/erts/emulator/beam/erl_db_hash.h b/erts/emulator/beam/erl_db_hash.h
index 830dc77114..cba7163479 100644
--- a/erts/emulator/beam/erl_db_hash.h
+++ b/erts/emulator/beam/erl_db_hash.h
@@ -25,8 +25,11 @@
 
 typedef struct fixed_deletion {
     UWord slot : sizeof(UWord)*8 - 2;
-    UWord all : 1;
+
+    /* Used by delete_all_objects: */
+    UWord all : 1;  /* marks [0 -> slot] */
     UWord trap : 1;
+
     struct fixed_deletion *next;
 } FixedDeletion;
 
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 588096301d..a1542247c3 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -42,6 +42,7 @@
 -export([foldl_ordered/1, foldr_ordered/1, foldl/1, foldr/1, fold_empty/1]).
 -export([t_delete_object/1, t_init_table/1, t_whitebox/1,
          select_bound_chunk/1, t_delete_all_objects/1, t_test_ms/1,
+         t_delete_all_objects_trap_unfix/1,
 	 t_select_delete/1,t_select_replace/1,t_select_replace_next_bug/1,
          t_select_pam_stack_overflow_bug/1,
          t_select_flatmap_term_copy_bug/1,
@@ -149,6 +150,7 @@ all() ->
      match_heavy, {group, fold}, member, t_delete_object,
      select_bound_chunk,
      t_init_table, t_whitebox, t_delete_all_objects,
+     t_delete_all_objects_trap_unfix,
      t_test_ms, t_select_delete, t_select_replace,
      t_select_replace_next_bug,
      t_select_pam_stack_overflow_bug,
@@ -960,7 +962,7 @@ get_kept_objects(T) ->
     end.
 
 t_delete_all_objects_do(Opts) ->
-    KeyRange = 4000,
+    KeyRange = 40_000,
     T=ets_new(x, Opts, KeyRange),
     filltabint(T,KeyRange),
     O=ets:first(T),
@@ -1039,6 +1041,63 @@ inserter(T, Next, Papa) ->
     end.
 
 
+%% Test unfix during delete_all_objects
+t_delete_all_objects_trap_unfix(Config) when is_list(Config) ->
+    EtsMem = etsmem(),
+    repeat_for_opts_all_set_table_types(
+      fun(Opts) ->
+              delete_all_objects_trap_unfix(Opts, unfix),
+              delete_all_objects_trap_unfix(Opts, exit)
+      end),
+    verify_etsmem(EtsMem),
+    ok.
+
+delete_all_objects_trap_unfix(Opts, Mode) ->
+    io:format("Opts = ~p\nMode = ~p\n", [Opts, Mode]),
+    Tester = self(),
+    KeyRange = 50_000,
+    T=ets_new(x, Opts, KeyRange),
+    filltabint(T, KeyRange),
+    KeyRange = ets:info(T,size),
+    FixerFun =
+        fun() ->
+                erlang:trace(Tester, true, [running]),
+                ets:safe_fixtable(T, true),
+                io:format("Wait for ets:delete_all_objects/1 to yield...\n", []),
+                Tester ! {safe_fixtable, self()},
+                repeat_while(
+                  fun() ->
+                          case receive_any() of
+                              {trace, Tester, out, {ets,internal_delete_all,2}} ->
+                                  false;
+                              "delete_all_objects done" ->
+                                  ct:fail("No trap detected");
+                              M ->
+                                  %%io:format("Ignored msg: ~p\n", [M]),
+                                  true
+                          end
+                  end),
+                case Mode of
+                    unfix ->
+                        io:format("Unfix table and then exit...\n",[]),
+                        ets:safe_fixtable(T, false);
+                    exit ->
+                        %%io:format("Exit and do auto-unfix...\n",[]),
+                        exit
+                end
+        end,
+    {Fixer, Mon} = spawn_opt(FixerFun, [link, monitor]),
+    {safe_fixtable, Fixer} = receive_any(),
+    true = ets:delete_all_objects(T),
+    Fixer ! "delete_all_objects done",
+    0 = ets:info(T,size),
+    {'DOWN', Mon, process, Fixer, normal} = receive_any(),
+    0 = get_kept_objects(T),
+    false = ets:info(T,safe_fixed),
+    ets:delete(T),
+    ok.
+
+
 %% Test ets:delete_object/2.
 t_delete_object(Config) when is_list(Config) ->
     EtsMem = etsmem(),
-- 
2.35.3

openSUSE Build Service is sponsored by