From f5a1c56f0ab2a276b5c2add54b8b0d6d276e1361 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 12 Aug 2016 16:18:25 +0200 Subject: erts: Fix port monitor memory leak --- erts/emulator/beam/erl_process.c | 1 - erts/emulator/test/port_SUITE.erl | 25 +++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'erts') diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index b5d8c5bc75..aa6af7427c 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -12276,7 +12276,6 @@ static void doit_exit_monitor(ErtsMonitor *mon, void *vpcontext) erts_port_demonitor(pcontext->p, ERTS_PORT_DEMONITOR_ORIGIN_ON_DEATHBED, prt, mon->ref, NULL); - return; /* let erts_port_demonitor do the deletion */ } else { /* remote by pid */ ASSERT(is_external_pid(mon->pid)); dep = external_pid_dist_entry(mon->pid); diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl index 5c0bfdffd4..a9814d7df9 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -104,6 +104,7 @@ mon_port_name_demonitor/1, mon_port_named/1, mon_port_origin_dies/1, + mon_port_owner_dies/1, mon_port_pid_demonitor/1, mon_port_remote_on_remote/1, mon_port_driver_die/1, @@ -173,6 +174,7 @@ all() -> mon_port_remote_on_remote, mon_port_bad_remote_on_local, mon_port_origin_dies, + mon_port_owner_dies, mon_port_named, mon_port_bad_named, mon_port_pid_demonitor, @@ -2637,6 +2639,29 @@ mon_port_origin_dies(Config) -> Port5 ! {self(), {command, <<"1">>}}, % make port quit ok. +%% Port and Monitor owner dies before port is closed +%% This testcase checks for a regression memory leak in erts +%% when the controlling and monitoring process is the same process +%% and the process dies +mon_port_owner_dies(Config) -> + Self = self(), + Proc = spawn(fun() -> + Port = create_port(Config, ["-h1", "-q"]), + Self ! {test_started, Port}, + erlang:monitor(port, Port), + receive stop -> ok end + end), + erlang:monitor(process, Proc), % we want to sync with its death + Port = receive {test_started,P} -> P + after 1000 -> ?assert(false) end, + ?assertMatch({proc_monitors, true, port_monitored_by, true}, + port_is_monitored(Proc, Port)), + Proc ! stop, + %% receive from monitor + receive ExitP5 -> ?assertMatch({'DOWN', _, process, Proc, _}, ExitP5) + after 1000 -> ?assert(false) end, + ok. + %% Monitor a named port mon_port_named(Config) -> Name6 = test_port6, -- cgit v1.2.3