我对Erlang中的跟踪器有疑问,以及如何在不丢失任何跟踪事件的情况下打开和关闭这些跟踪器。假设我有一个使用send
和receive
跟踪标志跟踪的进程P1,如下所示:
erlang:trace(P1Pid, true, [set_on_spawn, send, 'receive', {tracer, T1Pid}])
由于指定了set_on_spawn
标志,一旦(子)过程P2由P1产生,相同的标志(即 set_on_spawn
,send
,'receive'
)也适用于P2。现在假设我想在P2上创建一个新的跟踪器,这样跟踪器T1处理来自P1的跟踪,跟踪器T2处理来自P2的跟踪。为了做到这一点,(因为Erlang每个进程只允许一个跟踪器),我需要首先取消设置跟踪标志( ie set_on_spawn
,send
,{{1 }})来自P2(由于'receive'
标志会自动继承)和P2上的再次设置,如下所示:
set_on_spawn
在设置和取消设置跟踪器之间的行中,由于此处的竞争条件,进程P2引发的许多跟踪事件可能会丢失。
我的问题是:这可以在不丢失跟踪事件的情况下实现吗?
Erlang是否提供了以“原子方式”进行“跟踪器切换”(即从T1到T2)的方法?
或者,是否可以暂停Erlang VM并暂停跟踪,从而避免丢失跟踪事件?
答案 0 :(得分:0)
我已经深入研究了这个问题,并且可能找到了一个半理想的(见下文)部分解决方案。阅读Erlang文档后,我遇到了erlang:suspend_process/1
和erlang:resume_process/1
个BIF。使用这两个,我可以实现所需的行为:
% Suspend process P2. According to the Erlang docs, this function
% blocks the caller (i.e. the current tracer) until P2 is suspended.
% This way, we do not lose trace events.
erlang:suspend_process(P2Pid),
% Unset trace flags on P2.
erlang:trace(P2Pid, false, [set_on_spawn, send, 'receive']),
% We should not lose any trace events from P2, since it is
% currently suspended, and therefore cannot generate any.
% However, we can still lose receive trace events that are
% generated as a result of other processes sending messages
% to P2.
% Now set again trace flags on P2, directing the trace to
% a new tracer T2.
erlang:trace(P2Pid, true, [set_on_spawn, send, 'receive', {tracer, T2Pid}]),
% Finally, resume process P2, so that we can receive any trace
% messages generated by P2 on the new tracer T2.
erlang:resume_process(P2Pid).
使用此方法的唯一三个问题如下:
erlang:resume_process/1
这一事实)?{trace, Pid, receive, ...}
跟踪事件,这些事件在我们切换跟踪时可能会丢失。有没有办法可以避免这种情况? NB :先前由流程P'如果P'是自动恢复 (调用erlang:suspend_process/1
的那个)死了。