From d154a389cada12bed67e35c4875965d6a8933d2c Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Wed, 29 Nov 2023 22:54:14 +0100 Subject: [PATCH 1/2] [erts] Fix memory leak of fragmented message to unaliased process --- erts/emulator/beam/dist.c | 3 +- erts/emulator/beam/erl_proc_sig_queue.c | 8 ++- erts/emulator/test/process_SUITE.erl | 84 ++++++++++++++++++++++++- 3 files changed, 91 insertions(+), 4 deletions(-) diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c index 0967b9480997..4ed7ce246069 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -2452,11 +2452,12 @@ int erts_net_message(Port *prt, if (!is_external_pid(watcher)) goto invalid_message; if (erts_this_dist_entry == external_pid_dist_entry(watcher)) - break; + goto monitored_process_not_alive; goto invalid_message; } if (!erts_proc_lookup(watcher)) { + monitored_process_not_alive: if (ede_hfrag != NULL) { erts_free_dist_ext_copy(erts_get_dist_ext(ede_hfrag)); free_message_buffer(ede_hfrag); diff --git a/erts/emulator/beam/erl_proc_sig_queue.c b/erts/emulator/beam/erl_proc_sig_queue.c index 83b6991809d1..dbc0be63de29 100644 --- a/erts/emulator/beam/erl_proc_sig_queue.c +++ b/erts/emulator/beam/erl_proc_sig_queue.c @@ -1565,8 +1565,14 @@ erts_proc_sig_send_dist_to_alias(Eterm alias, ErtsDistExternal *edep, ASSERT(is_ref(alias)); pid = erts_get_pid_of_ref(alias); - if (!is_internal_pid(pid)) + if (!is_internal_pid(pid)) { + if (hfrag) { + /* Fragmented message... */ + erts_free_dist_ext_copy(erts_get_dist_ext(hfrag)); + free_message_buffer(hfrag); + } return; + } /* * The receiver can distinguish between these two scenarios by diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index f5abc2cdbd24..a977f75378ff 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -79,6 +79,8 @@ spawn_new_node/1, spawn_request_reply_option/1, alias_bif/1, + dist_frag_alias/1, + dist_frag_unaliased/1, monitor_alias/1, spawn_monitor_alias/1, monitor_tag/1]). @@ -149,7 +151,8 @@ 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, + dist_frag_alias, dist_frag_unaliased]}]. init_per_suite(Config) -> A0 = case application:start(sasl) of @@ -4078,7 +4081,84 @@ alias_bif_test(Node) -> end), [{A3,1},{'DOWN', M3, _, _, _}] = recv_msgs(2), ok. - + +dist_frag_alias(Config) when is_list(Config) -> + Tester = self(), + {ok, Node} = start_node(Config), + {P,M} = spawn_monitor(Node, + fun () -> + Alias = alias(), + Tester ! {alias, Alias}, + receive + {data, Data} -> + garbage_collect(), + Tester ! {received_data, Data} + end, + exit(end_of_test) + end), + Data = term_to_binary(lists:seq(1, 1000000)), + receive + {alias, Alias} -> + Alias ! {data, Data}, + receive + {received_data, RecvData} -> + Data = RecvData; + {'DOWN', M, process, P, R2} -> + ct:fail(R2) + end; + {'DOWN', M, process, P, R1} -> + ct:fail(R1) + end, + receive + {'DOWN', M, process, P, R3} -> + end_of_test = R3 + end, + stop_node(Node), + ok. + +dist_frag_unaliased(Config) when is_list(Config) -> + %% Leak fixed by PR-7915 would have been detected using asan or valgrind + %% when running this test... + Tester = self(), + {ok, Node} = start_node(Config), + {P,M} = spawn_monitor(Node, + fun () -> + Alias = alias(), + Tester ! {alias, Alias}, + receive + {data, Data} -> + garbage_collect(), + unalias(Alias), + Tester ! {received_data, Data}, + receive + {data, _Data} -> + exit(received_data_again); + end_of_test -> + exit(end_of_test) + end + end + end), + Data = term_to_binary(lists:seq(1, 1000000)), + receive + {alias, Alias} -> + Alias ! {data, Data}, + receive + {received_data, RecvData} -> + Data = RecvData; + {'DOWN', M, process, P, R2} -> + ct:fail(R2) + end, + Alias ! {data, Data}, + P ! end_of_test; + {'DOWN', M, process, P, R1} -> + ct:fail(R1) + end, + receive + {'DOWN', M, process, P, R3} -> + end_of_test = R3 + end, + stop_node(Node), + ok. monitor_alias(Config) when is_list(Config) -> monitor_alias_test(node()), From d94af94dde8331fb5352a5a2dd0b7e62824e92ae Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Thu, 30 Nov 2023 16:25:04 +0100 Subject: [PATCH 2/2] [erts] Fix crash on reception of fragmentated message to unaliased process --- erts/emulator/beam/erl_proc_sig_queue.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/erts/emulator/beam/erl_proc_sig_queue.c b/erts/emulator/beam/erl_proc_sig_queue.c index dbc0be63de29..1dd8641ebe0a 100644 --- a/erts/emulator/beam/erl_proc_sig_queue.c +++ b/erts/emulator/beam/erl_proc_sig_queue.c @@ -4837,8 +4837,6 @@ handle_alias_message(Process *c_p, ErtsMessage *sig, ErtsMessage ***next_nm_sig) ASSERT(is_internal_pid(from) || is_atom(from)); ASSERT(is_internal_pid_ref(alias)); - ERL_MESSAGE_FROM(sig) = from; - mon = erts_monitor_tree_lookup(ERTS_P_MONITORS(c_p), alias); flags = mon ? mon->flags : (Uint16) 0; if (!(flags & ERTS_ML_STATE_ALIAS_MASK) @@ -4848,17 +4846,13 @@ handle_alias_message(Process *c_p, ErtsMessage *sig, ErtsMessage ***next_nm_sig) * drop message... */ remove_nm_sig(c_p, sig, next_nm_sig); - /* restored as message... */ - ERL_MESSAGE_TERM(sig) = msg; - if (type == ERTS_SIG_Q_TYPE_DIST) - sig->data.heap_frag = &sig->hfrag; - else - sig->data.attached = data_attached; sig->next = NULL;; erts_cleanup_messages(sig); return 2; } + ERL_MESSAGE_FROM(sig) = from; + if ((flags & ERTS_ML_STATE_ALIAS_MASK) == ERTS_ML_STATE_ALIAS_ONCE) { mon->flags &= ~ERTS_ML_STATE_ALIAS_MASK;