From 419356c33742613adcdf6d09ba25361baa406c2d Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Wed, 1 Mar 2023 18:03:07 +0100 Subject: [PATCH] [erts] Ensure cleanup of alias table on alias destruction --- erts/emulator/beam/erl_bif_info.c | 10 ++++++ erts/emulator/beam/erl_bif_unique.c | 21 ++++++++++++ erts/emulator/beam/erl_bif_unique.h | 2 +- erts/emulator/beam/erl_monitor_link.c | 10 ++++++ erts/emulator/test/process_SUITE.erl | 49 ++++++++++++++++++++++++++- 5 files changed, 90 insertions(+), 2 deletions(-) diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index d5e598515c64..41820932cad6 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -4149,6 +4149,16 @@ BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1) else if (ERTS_IS_ATOM_STR("persistent_term", BIF_ARG_1)) { BIF_RET(erts_debug_persistent_term_xtra_info(BIF_P)); } + else if (ERTS_IS_ATOM_STR("pid_ref_table_size", BIF_ARG_1)) { + Uint size = erts_pid_ref_table_size(); + if (IS_SSMALL(size)) + BIF_RET(make_small(size)); + else { + Uint hsz = BIG_UWORD_HEAP_SIZE(size); + Eterm *hp = HAlloc(BIF_P, hsz); + BIF_RET(uword_to_big(size, hp)); + } + } } else if (is_tuple(BIF_ARG_1)) { Eterm* tp = tuple_val(BIF_ARG_1); diff --git a/erts/emulator/beam/erl_bif_unique.c b/erts/emulator/beam/erl_bif_unique.c index 0deced34deb9..ec118af1d262 100644 --- a/erts/emulator/beam/erl_bif_unique.c +++ b/erts/emulator/beam/erl_bif_unique.c @@ -701,6 +701,27 @@ init_pid_ref_tables(void) } } + +Uint +erts_pid_ref_table_size(void) +{ + int i; + Uint sz = 0; + + for (i = 0; i <= erts_no_schedulers; i++) { + HashInfo hi; + ErtsPidRefTable *tblp = &pid_ref_table[i].u.table; + erts_rwmtx_rlock(&tblp->rwmtx); + hash_get_info(&hi, &tblp->hash); + erts_rwmtx_runlock(&tblp->rwmtx); + sz += (Uint) hi.objs; + } + + return sz; +} + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Unique Integer * \* */ diff --git a/erts/emulator/beam/erl_bif_unique.h b/erts/emulator/beam/erl_bif_unique.h index 58426b0b55d1..b6b15c570c51 100644 --- a/erts/emulator/beam/erl_bif_unique.h +++ b/erts/emulator/beam/erl_bif_unique.h @@ -42,7 +42,7 @@ void erts_magic_ref_save_bin__(Eterm ref); ErtsMagicBinary *erts_magic_ref_lookup_bin__(Uint32 refn[ERTS_REF_NUMBERS]); void erts_pid_ref_delete(Eterm ref); Eterm erts_pid_ref_lookup__(Uint32 refn[ERTS_REF_NUMBERS]); - +Uint erts_pid_ref_table_size(void); /* strict monotonic counter */ diff --git a/erts/emulator/beam/erl_monitor_link.c b/erts/emulator/beam/erl_monitor_link.c index 23fd3dd56645..d06b78e1ab39 100644 --- a/erts/emulator/beam/erl_monitor_link.c +++ b/erts/emulator/beam/erl_monitor_link.c @@ -1094,6 +1094,16 @@ erts_monitor_destroy__(ErtsMonitorData *mdp) || ((mdp->origin.flags & ERTS_ML_FLGS_SAME) == (mdp->u.target.flags & ERTS_ML_FLGS_SAME))); + if (mdp->origin.flags & ERTS_ML_STATE_ALIAS_MASK) { + ASSERT(mdp->origin.type == ERTS_MON_TYPE_ALIAS + || mdp->origin.type == ERTS_MON_TYPE_PROC + || mdp->origin.type == ERTS_MON_TYPE_PORT + || mdp->origin.type == ERTS_MON_TYPE_TIME_OFFSET + || mdp->origin.type == ERTS_MON_TYPE_DIST_PROC + || mdp->origin.type == ERTS_MON_TYPE_DIST_PORT); + erts_pid_ref_delete(mdp->ref); + } + switch (mdp->origin.type) { case ERTS_MON_TYPE_ALIAS: ERTS_ML_ASSERT(!(mdp->origin.flags & ERTS_ML_FLG_TAG)); diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index f5abc2cdbd24..567c240a4ada 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -81,6 +81,7 @@ alias_bif/1, monitor_alias/1, spawn_monitor_alias/1, + alias_process_exit/1, monitor_tag/1]). -export([prio_server/2, prio_client/2, init/1, handle_event/2]). @@ -149,7 +150,7 @@ groups() -> gc_request_when_gc_disabled, gc_request_blast_when_gc_disabled, otp_16436, otp_16642]}, {alias, [], - [alias_bif, monitor_alias, spawn_monitor_alias]}]. + [alias_bif, monitor_alias, spawn_monitor_alias, alias_process_exit]}]. init_per_suite(Config) -> A0 = case application:start(sasl) of @@ -168,9 +169,15 @@ end_per_suite(Config) -> catch erts_debug:set_internal_state(available_internal_state, false), Config. +init_per_group(alias, Config) -> + erts_debug:set_internal_state(available_internal_state, true), + Config; init_per_group(_GroupName, Config) -> Config. +end_per_group(alias, Config) -> + erts_debug:set_internal_state(available_internal_state, false), + Config; end_per_group(_GroupName, Config) -> Config. @@ -4032,11 +4039,25 @@ otp_16642(Config) when is_list(Config) -> false = is_process_alive(Pid), ok. +pid_ref_table_size() -> + erts_debug:get_internal_state(pid_ref_table_size). + +check_pid_ref_table_size(PRTSz) -> + receive after 500 -> ok end, + case pid_ref_table_size() of + PRTSz -> + ok; + NewPRTSz -> + ct:fail({port_ref_table_size_mismatch, PRTSz, NewPRTSz}) + end. + alias_bif(Config) when is_list(Config) -> + PRTSz = pid_ref_table_size(), alias_bif_test(node()), {ok, Node} = start_node(Config), alias_bif_test(Node), stop_node(Node), + check_pid_ref_table_size(PRTSz), ok. alias_bif_test(Node) -> @@ -4081,10 +4102,12 @@ alias_bif_test(Node) -> monitor_alias(Config) when is_list(Config) -> + PRTSz = pid_ref_table_size(), monitor_alias_test(node()), {ok, Node} = start_node(Config), monitor_alias_test(Node), stop_node(Node), + check_pid_ref_table_size(PRTSz), ok. monitor_alias_test(Node) -> @@ -4168,6 +4191,7 @@ monitor_alias_test(Node) -> spawn_monitor_alias(Config) when is_list(Config) -> %% Exit signals with immediate exit reasons are sent %% in a different manner than compound exit reasons. + PRTSz = pid_ref_table_size(), spawn_monitor_alias_test(node(), spawn_opt, normal), spawn_monitor_alias_test(node(), spawn_opt, make_ref()), spawn_monitor_alias_test(node(), spawn_request, normal), @@ -4180,6 +4204,7 @@ spawn_monitor_alias(Config) when is_list(Config) -> spawn_monitor_alias_test(Node3, spawn_request, normal), {ok, Node4} = start_node(Config), spawn_monitor_alias_test(Node4, spawn_request, make_ref()), + check_pid_ref_table_size(PRTSz), ok. spawn_monitor_alias_test(Node, SpawnType, ExitReason) -> @@ -4320,6 +4345,28 @@ spawn_monitor_alias_test(Node, SpawnType, ExitReason) -> ok end. +alias_process_exit(Config) when is_list(Config) -> + Tester = self(), + CreatedAliases = make_ref(), + PRTSz = pid_ref_table_size(), + P = spawn_link(fun () -> + A0 = alias([explicit_unalias]), + A1 = alias([reply]), + A2 = monitor(process, Tester, [{alias, explicit_unalias}]), + A3 = monitor(process, Tester, [{alias, demonitor}]), + A4 = monitor(process, Tester, [{alias, reply_demonitor}]), + Tester ! CreatedAliases, + receive after infinity -> ok end, + some_module:some_function([A0, A1, A2, A3, A4]) + end), + receive CreatedAliases -> ok end, + PRTSz = erts_debug:get_internal_state(pid_ref_table_size) - 5, + unlink(P), + exit(P, kill), + false = is_process_alive(P), + check_pid_ref_table_size(PRTSz), + ok. + monitor_tag(Config) when is_list(Config) -> %% Exit signals with immediate exit reasons are sent %% in a different manner than compound exit reasons, and