我有一个项目,它有很多模块,每个模块都有不同的运行线程。我写了一个小脚本,它遍历每个脚本并安全地重新加载代码(用于热交换):
reload_all() ->
?MODULE:reload_all(?MODULE_LIST).
reload_all([]) -> ok;
reload_all([T|C]) ->
io:fwrite("Purging ~w\n",[T]),
try_purge(T),
{module,T} = code:load_file(T),
?MODULE:reload_all(C).
try_purge(T) -> try_purge(T,1).
try_purge(T,Wait) ->
case code:soft_purge(T) of
true -> ok;
false ->
io:fwrite("* Waiting ~w seconds for ~w module\n",[Wait,T]),
timer:sleep(Wait*1000),
try_purge(T,Wait+1)
end.
它使用 soft_purge() 函数,该函数仅在没有线程运行将被正常清除命令杀死的“旧”代码时清除代码。它将以越来越长的间隔等待并继续尝试。我已经设计了这个项目,因此等待总时间不应该超过一分钟,但实际上它应该或多或少是即时的。
我遇到的问题是,有时一个模块会有一个错误,导致它由于某种原因无限期地阻塞,而我的 reload_all() 脚本永远不会完成。这是期望的行为,它让我知道出了点问题。问题在于,追踪 bug 需要对代码进行大量的测试和分析,这有时甚至不起作用,因为 bug 只出现在生产环境中,而不出现在测试环境中。
我的问题是:有没有办法识别哪些线程正在运行模块中的“旧”代码,并查看它们当前卡在哪个函数中?