停止并启动Erlang跟踪器而不会丢失跟踪事件

时间:2016-06-13 10:49:59

标签: erlang tracing

我对Erlang中的跟踪器有疑问,以及如何在不丢失任何跟踪事件的情况下打开和关闭这些跟踪器。假设我有一个使用sendreceive跟踪标志跟踪的进程P1,如下所示:

erlang:trace(P1Pid, true, [set_on_spawn, send, 'receive', {tracer, T1Pid}])

由于指定了set_on_spawn标志,一旦(子)过程P2由P1产生,相同的标志( set_on_spawnsend'receive')也适用于P2。现在假设我想在P2上创建一个新的跟踪器,这样跟踪器T1处理来自P1的跟踪,跟踪器T2处理来自P2的跟踪。为了做到这一点,(因为Erlang每个进程只允许一个跟踪器),我需要首先取消设置跟踪标志( ie set_on_spawnsend,{{1 }})来自P2(由于'receive'标志会自动继承)和P2上的再次设置,如下所示:

set_on_spawn

在设置和取消设置跟踪器之间的行中,由于此处的竞争条件,进程P2引发的许多跟踪事件可能会丢失。

我的问题是:这可以在不丢失跟踪事件的情况下实现吗?

Erlang是否提供了以“原子方式”进行“跟踪器切换”(从T1到T2)的方法?

或者,是否可以暂停Erlang VM并暂停跟踪,从而避免丢失跟踪事件?

1 个答案:

答案 0 :(得分:0)

我已经深入研究了这个问题,并且可能找到了一个半理想的(见下文)部分解决方案。阅读Erlang文档后,我遇到了erlang:suspend_process/1erlang: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).

使用此方法的唯一三个问题如下:

  1. erlang:suspend_process/1erlang:resume_process/1的Erlang文档明确声明这些文档仅用于调试目的。我的问题是,为什么不能在生产中使用这些,如示例所示,除非过程P2被暂停,否则我们面临丢失跟踪事件的风险(从跟踪器T1切换到跟踪器T2)?
  2. 我们实际上正在搞乱系统(我们正在干扰它的调度)。是否存在与此相关的风险(除了可以忘记在先前暂停的流程上调用erlang:resume_process/1这一事实)?
  3. 更重要的是,即使我们可以阻止进程P2采取任何操作,我们也无法阻止其他进程向P2发送消息。这些消息将导致{trace, Pid, receive, ...}跟踪事件,这些事件在我们切换跟踪时可能会丢失。有没有办法可以避免这种情况?
  4. NB :先前由流程P'如果P'是自动恢复 (调用erlang:suspend_process/1的那个)死了。