From d89925ce7b7222dd2f871054a6a254aad3e62ac7 Mon Sep 17 00:00:00 2001 From: Thales Macedo Garitezi Date: Tue, 22 Feb 2022 16:31:35 -0300 Subject: [PATCH 1/3] fix(sys_mon): guard before calling `erlang:port_info` Sometimes, the `emqx_sys_mon:procinfo/1` might be called with something that is not a port, like `[]`. Not sure on the conditions for this to happen. ``` 2022-02-18T20:05:02.671592+00:00 [error] Generic server emqx_sys_mon terminating. Reason: {badarg,[{erlang,port_info,[[]],[{error_info,#{module => erl_erts_errors}}]},{emqx_sys_mon,portinfo,1,[{file,"/emqx/apps/emqx/src/emqx_sys_mon.erl"},{line,205}]},{emqx_sys_mon,'-handle_info/2-fun-5-',2,[{file,"/emqx/apps/emqx/src/emqx_sys_mon.erl"},{line,150}]},{emqx_sys_mon,suppress,3,[{file,"/emqx/apps/emqx/src/emqx_sys_mon.erl"},{line,184}]},{gen_server,try_dispatch,4,[{file,"gen_server.erl"},{line,695}]},{gen_server,handle_msg,6,[{file,"gen_server.erl"},{line,771}]},{proc_lib,wake_up,3,[{file,"proc_lib.erl"},{line,236}]}]}. Last message: {monitor,<0.7796.0>,busy_dist_port,[]}. State: #{events => [{busy_dist_port,#Port<0.127>}],timer => #Ref<0.2758388682.1853620226.133920>}. ``` --- apps/emqx/src/emqx_sys_mon.erl | 7 ++++++- apps/emqx/test/emqx_sys_mon_SUITE.erl | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/emqx/src/emqx_sys_mon.erl b/apps/emqx/src/emqx_sys_mon.erl index 1f8f04d97..1df9ec604 100644 --- a/apps/emqx/src/emqx_sys_mon.erl +++ b/apps/emqx/src/emqx_sys_mon.erl @@ -202,7 +202,12 @@ get_proc_lib_initial_call(Pid) -> end. portinfo(Port) -> - [{port, Port} | erlang:port_info(Port)]. + PortInfo = + case is_port(Port) andalso erlang:port_info(Port) of + L when is_list(L) -> L; + _ -> [] + end, + [{port, Port} | PortInfo]. safe_publish(Event, WarnMsg) -> Topic = emqx_topic:systop(lists:concat(['sysmon/', Event])), diff --git a/apps/emqx/test/emqx_sys_mon_SUITE.erl b/apps/emqx/test/emqx_sys_mon_SUITE.erl index 8e4bd65db..31acd885f 100644 --- a/apps/emqx/test/emqx_sys_mon_SUITE.erl +++ b/apps/emqx/test/emqx_sys_mon_SUITE.erl @@ -35,6 +35,11 @@ {self(), busy_port, fmt("busy_port warning: suspid = ~p, port = ~p", [self(), ?FAKE_PORT]), ?FAKE_PORT}, + %% for the case when the port is missing, for some + %% reason. + {self(), busy_port, + fmt("busy_port warning: suspid = ~p, port = ~p", + [self(), []]), []}, {self(), busy_dist_port, fmt("busy_dist_port warning: suspid = ~p, port = ~p", [self(), ?FAKE_PORT]), ?FAKE_PORT}, From 427866f8adb5376e0da31acd37f9e8e6fd947599 Mon Sep 17 00:00:00 2001 From: Thales Macedo Garitezi Date: Thu, 24 Feb 2022 15:13:18 -0300 Subject: [PATCH 2/3] test(sys_mon): add test for closed port --- apps/emqx/test/emqx_sys_mon_SUITE.erl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/apps/emqx/test/emqx_sys_mon_SUITE.erl b/apps/emqx/test/emqx_sys_mon_SUITE.erl index 31acd885f..c14074f0d 100644 --- a/apps/emqx/test/emqx_sys_mon_SUITE.erl +++ b/apps/emqx/test/emqx_sys_mon_SUITE.erl @@ -125,6 +125,16 @@ t_sys_mon(_Config) -> validate_sys_mon_info(PidOrPort, SysMonName, ValidateInfo, InfoOrPort) end, ?INPUTINFO). +%% Existing port, but closed. +t_sys_mon_dead_port(_Config) -> + process_flag(trap_exit, true), + Port = dead_port(), + {PidOrPort, SysMonName, ValidateInfo, InfoOrPort} = + {self(), busy_port, + fmt("busy_port warning: suspid = ~p, port = ~p", + [self(), Port]), Port}, + validate_sys_mon_info(PidOrPort, SysMonName, ValidateInfo, InfoOrPort). + t_sys_mon2(_Config) -> ?SYSMON ! {timeout, ignored, reset}, ?SYSMON ! {ignored}, @@ -156,3 +166,8 @@ some_function(Parent, _Arg2) -> stop -> ok end. + +dead_port() -> + Port = erlang:open_port({spawn, "ls"}, []), + catch exit(Port, kill), + Port. From 0e319d5e4e0b32e75e1cb53bbc11ac328e100524 Mon Sep 17 00:00:00 2001 From: Thales Macedo Garitezi Date: Thu, 24 Feb 2022 16:28:00 -0300 Subject: [PATCH 3/3] fix: rm useless `catch` --- apps/emqx/test/emqx_sys_mon_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/emqx/test/emqx_sys_mon_SUITE.erl b/apps/emqx/test/emqx_sys_mon_SUITE.erl index c14074f0d..338188c21 100644 --- a/apps/emqx/test/emqx_sys_mon_SUITE.erl +++ b/apps/emqx/test/emqx_sys_mon_SUITE.erl @@ -169,5 +169,5 @@ some_function(Parent, _Arg2) -> dead_port() -> Port = erlang:open_port({spawn, "ls"}, []), - catch exit(Port, kill), + exit(Port, kill), Port.