在不通过通用测试的情况下杀死 gen_server
Posted
技术标签:
【中文标题】在不通过通用测试的情况下杀死 gen_server【英文标题】:Killing a gen_server without failing the Common Test 【发布时间】:2021-09-25 15:30:15 【问题描述】:我实现了一个故意崩溃的模块(以测试另一个模块的功能,该模块正在监视它)。问题是,当这个 gen_server 崩溃时,它也会导致通用测试失败。我尝试使用 try/catch 并设置 process_flag(trap_exit, true)
,但似乎没有任何效果。
以下是一些相关代码:
-module(mod_bad_process).
% ...
%% ct calls this function directly
kill() ->
gen_server:call(?MODULE, update_behavior, kill).
% ...
handle_cast(update_behavior, Behavior, _From, State) ->
case Behavior of
kill -> stop, killed, State;
_ -> reply, ok, State#state := Behavior
end;
% ...
以及常见的测试:
% ...
-define(BAD_PROC, mod_bad_process).
% ...
remonitor_test(_Conf) ->
InitialPid = whereis(?BAD_PROC),
true = undefined =/= InitialPid,
true = is_monitored_gen_server(?BAD_PROC),
mod_bad_process:kill(), % gen_server crashes
timer:sleep(?REMONITOR_DELAY_MS),
FinalPid = whereis(?BAD_PROC),
true = InitialPid =/= FinalPid,
true = undefined =/= FinalPid,
true = is_monitored_gen_server(?BAD_PROC).
% ...
还有来自 ct 的错误:
*** CT Error Notification 2021-07-16 16:08:20.791 ***
gen_server:call failed on line 238
Reason: killed,gen_server,call,...
=== Ended at 2021-07-16 16:08:20
=== Location: [gen_server,call,238,
mod_bad_process,kill,48,
monitor_tests,remonitor_test,62,
test_server,ts_tc,1784,
test_server,run_test_case_eval1,1293,
test_server,run_test_case_eval,1225]
=== === Reason: killed,gen_server,call,
[mod_bad_process_global,
update_behavior,kill]
===
*** monitor_remonitor_test failed.
Skipping all other cases in sequence.
关于如何在不通过常见测试的情况下获得此功能的任何想法?
【问题讨论】:
请显示常见的测试代码和崩溃。 CT码里是trap_exit
吗?
@JoséM 添加了通用测试代码。是的,我在mod_bad_process:kill()
之前尝试了trap_exit
。我还尝试将其包装在 try catch 中
您能分享一下 CT 报告的崩溃情况吗?另外,这 3 个进程(测试运行程序、监视器和 BAD_PROC)是如何链接在一起的?此外,它可能对您有用:您可以使用 process_info(...[links|monitors|monitored_by])
检查进程的链接和监视器
@JoséM 我更新了我的帖子以显示错误和堆栈跟踪。我不确定测试运行器是如何连接的,但是监视器正在监视 mod_bad_process(正如人们所期望的那样),并且它们都具有到未知进程的链接(可能是它们的主管,绝对不是彼此)。我想 mod_bad_process gen_server 可能链接到运行我的测试的进程,但我认为这不太可能,因为我以前有间接杀死 gen_server 的代码(基本上是通过将坏 proc 的状态设置为 kill
并等待它要检查),效果很好。
你的情况很像这个……medium.com/erlang-battleground/…
【参考方案1】:
问题是我的 try/catch 尝试与实际错误的模式不匹配。这是修复:
-module(mod_bad_process).
% ...
kill() ->
try gen_server:call(?MODULE, update_behavior, kill) of
_ -> error(failed_to_kill)
catch
exit:killed, _ -> ok
end.
% ...
【讨论】:
以上是关于在不通过通用测试的情况下杀死 gen_server的主要内容,如果未能解决你的问题,请参考以下文章
如何在不显示通知的情况下 startForeground()?
如何在不杀死未完成的芹菜任务的情况下重新启动heroku应用程序
如何在不“杀死” Unity 的情况下在 Ubuntu 14.04 中安装 Matlab MCR?
Firebase crashlytics 中的非致命错误能否在不杀死应用程序 React Native 的情况下记录错误