From 625a9838ee4e494d5c055986ceff66a32c38a05c Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 16 Nov 2018 19:49:11 +0100 Subject: erts: Fix offheap leak of ets catree tmp iteration key Also fix erts_debug:get_internal_status(node_and_dist_references) for catree to also search route node keys for offheap stuff. --- erts/emulator/beam/erl_db_catree.c | 24 ++++++++++++++++++++++-- lib/stdlib/test/Makefile | 8 +++----- lib/stdlib/test/ets_SUITE.erl | 18 ++++++------------ 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/erts/emulator/beam/erl_db_catree.c b/erts/emulator/beam/erl_db_catree.c index 153a720f07..b642ae009d 100644 --- a/erts/emulator/beam/erl_db_catree.c +++ b/erts/emulator/beam/erl_db_catree.c @@ -811,11 +811,12 @@ void destroy_root_iterator(CATreeRootIterator* iter) { if (iter->locked_bnode) unlock_iter_base_node(iter); - if (iter->search_key) + if (iter->search_key) { + destroy_route_key(iter->search_key); erts_free(ERTS_ALC_T_DB_TMP, iter->search_key); + } } - typedef struct { DbTableCATreeNode *parent; @@ -2069,6 +2070,23 @@ static SWord db_delete_all_objects_catree(Process* p, DbTable* tbl, SWord reds) } +static void do_for_route_nodes(DbTableCATreeNode* node, + void (*func)(ErlOffHeap *, void *), + void *arg) +{ + ErlOffHeap tmp_offheap; + + if (!GET_LEFT(node)->is_base_node) + do_for_route_nodes(GET_LEFT(node), func, arg); + + tmp_offheap.first = node->u.route.key.oh; + tmp_offheap.overhead = 0; + (*func)(&tmp_offheap, arg); + + if (!GET_RIGHT(node)->is_base_node) + do_for_route_nodes(GET_RIGHT(node), func, arg); +} + static void db_foreach_offheap_catree(DbTable *tbl, void (*func)(ErlOffHeap *, void *), void *arg) @@ -2083,6 +2101,8 @@ static void db_foreach_offheap_catree(DbTable *tbl, root = catree_find_next_root(&iter, NULL); } while (root); destroy_root_iterator(&iter); + + do_for_route_nodes(GET_ROOT(&tbl->catree), func, arg); } static int db_lookup_dbterm_catree(Process *p, DbTable *tbl, Eterm key, Eterm obj, diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile index bbe3cefa42..712b1b92fb 100644 --- a/lib/stdlib/test/Makefile +++ b/lib/stdlib/test/Makefile @@ -99,11 +99,9 @@ MODULES= \ maps_SUITE \ zzz_SUITE -ERL_FILES= $(MODULES:%=%.erl) +ERTS_MODULES= erts_test_utils -TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) - -INSTALL_PROGS= $(TARGET_FILES) +ERL_FILES= $(MODULES:%=%.erl) $(ERTS_MODULES:%=$(ERL_TOP)/erts/emulator/test/%.erl) # ---------------------------------------------------- # Release directory specification @@ -128,7 +126,7 @@ COVERFILE=stdlib.cover # ---------------------------------------------------- make_emakefile: - $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \ + $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) $(ERTS_MODULES) \ > $(EMAKEFILE) tests debug opt: make_emakefile diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index cc369979f7..501588ad44 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -6052,7 +6052,7 @@ smp_ordered_iteration(Config) when is_list(Config) -> smp_ordered_iteration_do(Opts) -> KeyRange = 1000, - OffHeap = fun() -> dummy end, % To exercise key copy/destroy code. + OffHeap = erts_test_utils:mk_ext_pid({a@b,1}, 4711, 1), KeyFun = fun(K, Type) -> {K div 10, K rem 10, Type, OffHeap} end, @@ -6129,6 +6129,9 @@ smp_ordered_iteration_do(Opts) -> io:format("Stats = ~p\n", [ets:info(T,stats)]), io:format("Rounds = ~p\n", [Rounds]), true = ets:delete(T), + + %% Verify no leakage of offheap key data + ok = erts_test_utils:check_node_dist(), ok. incr_counter(Name, Counters) -> @@ -7455,9 +7458,6 @@ is_redundant_opts_combo(Opts) -> key_range(Opts, KeyRange) -> [{key_range, KeyRange} | Opts]. -key_range_fun(Opts, KeyRange, KeyFun) -> - [{key_range, KeyRange}, {key_fun, KeyFun} | Opts]. - ets_new(Name, Opts0) -> {KeyRange, Opts1} = case lists:keytake(key_range, 1, Opts0) of {value, {key_range, KR}, Rest1} -> @@ -7467,14 +7467,8 @@ ets_new(Name, Opts0) -> end, ets_new(Name, Opts1, KeyRange). -ets_new(Name, Opts1, KeyRange) -> - {KeyFun, Opts2} = case lists:keytake(key_fun, 1, Opts1) of - {value, {key_fun, KF}, Rest2} -> - {KF, Rest2}; - false -> - {fun id/1, Opts1} - end, - ets_new(Name, Opts2, KeyRange, KeyFun). +ets_new(Name, Opts, KeyRange) -> + ets_new(Name, Opts, KeyRange, fun id/1). ets_new(Name, Opts0, KeyRange, KeyFun) -> {CATree, Stimulate, RevOpts} = -- cgit v1.2.3