summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSverker Eriksson <sverker@erlang.org>2021-04-06 16:30:38 +0200
committerSverker Eriksson <sverker@erlang.org>2021-04-06 16:30:38 +0200
commita849b19ecb71402601f72a72eaa34f918b882932 (patch)
treebe96ac332f681e5b37481956c777c0de656c9235
parent53d2a7d511081d961df9ff497494feef43ca9674 (diff)
parentfb0c63315746fa503caaa949aba3aeb5c8286c08 (diff)
downloaderlang-a849b19ecb71402601f72a72eaa34f918b882932.tar.gz
Merge branch 'sverker/erts/persistent_term-get-0-race/OTP-17298' into maint
-rw-r--r--erts/emulator/beam/erl_bif_persistent.c8
-rw-r--r--erts/emulator/test/persistent_term_SUITE.erl40
2 files changed, 46 insertions, 2 deletions
diff --git a/erts/emulator/beam/erl_bif_persistent.c b/erts/emulator/beam/erl_bif_persistent.c
index 91cc03fe57..596604cdec 100644
--- a/erts/emulator/beam/erl_bif_persistent.c
+++ b/erts/emulator/beam/erl_bif_persistent.c
@@ -439,7 +439,7 @@ BIF_RETTYPE persistent_term_put_2(BIF_ALIST_2)
BIF_RETTYPE persistent_term_get_0(BIF_ALIST_0)
{
- HashTable* hash_table = (HashTable *) erts_atomic_read_nob(&the_hash_table);
+ HashTable* hash_table;
TrapData* trap_data;
Eterm res = NIL;
Eterm magic_ref;
@@ -450,6 +450,8 @@ BIF_RETTYPE persistent_term_get_0(BIF_ALIST_0)
ERTS_BIF_YIELD0(&bif_trap_export[BIF_persistent_term_get_0], BIF_P);
}
+ hash_table = (HashTable *) erts_atomic_read_nob(&the_hash_table);
+
magic_ref = alloc_trap_data(BIF_P);
mbp = erts_magic_ref2bin(magic_ref);
trap_data = ERTS_MAGIC_BIN_DATA(mbp);
@@ -673,7 +675,7 @@ BIF_RETTYPE erts_internal_erase_persistent_terms_0(BIF_ALIST_0)
BIF_RETTYPE persistent_term_info_0(BIF_ALIST_0)
{
- HashTable* hash_table = (HashTable *) erts_atomic_read_nob(&the_hash_table);
+ HashTable* hash_table;
TrapData* trap_data;
Eterm res = NIL;
Eterm magic_ref;
@@ -684,6 +686,8 @@ BIF_RETTYPE persistent_term_info_0(BIF_ALIST_0)
ERTS_BIF_YIELD0(&bif_trap_export[BIF_persistent_term_info_0], BIF_P);
}
+ hash_table = (HashTable *) erts_atomic_read_nob(&the_hash_table);
+
magic_ref = alloc_trap_data(BIF_P);
mbp = erts_magic_ref2bin(magic_ref);
trap_data = ERTS_MAGIC_BIN_DATA(mbp);
diff --git a/erts/emulator/test/persistent_term_SUITE.erl b/erts/emulator/test/persistent_term_SUITE.erl
index f4511eb483..a988864c2d 100644
--- a/erts/emulator/test/persistent_term_SUITE.erl
+++ b/erts/emulator/test/persistent_term_SUITE.erl
@@ -22,8 +22,10 @@
-include_lib("common_test/include/ct.hrl").
-export([all/0,suite/0,init_per_suite/1,end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2,
basic/1,purging/1,sharing/1,get_trapping/1,
destruction/1,
+ get_all_race/1,
info/1,info_trapping/1,killed_while_trapping/1,
off_heap_values/1,keys/1,collisions/1,
init_restart/1, put_erase_trapping/1,
@@ -40,6 +42,7 @@ suite() ->
all() ->
[basic,purging,sharing,get_trapping,info,info_trapping,
destruction,
+ get_all_race,
killed_while_trapping,off_heap_values,keys,collisions,
init_restart, put_erase_trapping, killed_while_trapping_put,
killed_while_trapping_erase].
@@ -56,6 +59,15 @@ end_per_suite(Config) ->
erts_debug:set_internal_state(available_internal_state, false),
Config.
+init_per_testcase(_, Config) ->
+ Config.
+
+end_per_testcase(_, _Config) ->
+ ok;
+end_per_testcase(get_all_race, _Config) ->
+ get_all_race_cleanup(),
+ ok.
+
basic(_Config) ->
Chk = chk(),
N = 777,
@@ -781,3 +793,31 @@ repeat(_Fun, 0) ->
repeat(Fun, N) ->
Fun(),
repeat(Fun, N-1).
+
+
+%% OTP-17298
+get_all_race(_Config) ->
+ N = 20 * erlang:system_info(schedulers_online),
+ persistent_term:put(get_all_race, N),
+ SPs = [spawn_link(fun() -> gar_setter(Seq) end) || Seq <- lists:seq(1, N)],
+ GPs = [spawn_link(fun gar_getter/0) || _ <- lists:seq(1, N)],
+ receive after 2000 -> ok end,
+ [begin unlink(Pid), exit(Pid,kill) end || Pid <- (SPs ++ GPs)],
+ ok.
+
+get_all_race_cleanup() ->
+ N = persistent_term:get(get_all_race, 0),
+ _ = persistent_term:erase(get_all_race),
+ [_ = persistent_term:erase(Seq) || Seq <- lists:seq(1, N)],
+ ok.
+
+gar_getter() ->
+ erts_debug:set_internal_state(reds_left, 1),
+ _ = persistent_term:get(),
+ gar_getter().
+
+gar_setter(Key) ->
+ erts_debug:set_internal_state(reds_left, 1),
+ persistent_term:erase(Key),
+ persistent_term:put(Key, {complex, term}),
+ gar_setter(Key).