如何使用BEAM VM的跟踪功能停止(安全地)在Elixir中进行跟踪?

时间:2016-07-07 15:45:19

标签: erlang elixir tracing

我一直在使用Elixir程序中:erlang.trace提供的功能收集数据。通过指定{:tracer, some_pid}选项,我可以让另一个进程获取进程中当前正在进行的所有操作的跟踪。这个输出非常有用。

我遇到的问题是如何在不崩溃VM的情况下停止跟踪进程。 :erlang.trace的文档在这里

http://erlang.org/doc/man/erlang.html#trace-3

我的假设是我可以将How设置为false并将我的选项设置为[:all]以禁用所有内容。

以下是我的示例程序

defmodule Example do
  def simple_tracer() do
    receive do 
      x -> IO.inspect(x); simple_tracer()
    end
  end

  def fancy_tracer() do
    receive do
      x -> IO.puts "fancy!" <> inspect(x); fancy_tracer
    end
  end
end

simple = spawn_link(&Example.simple_tracer/0)
fancy = spawn_link(&Example.fancy_tracer/0)

#Tell BEAM to trace everything
:erlang.trace_pattern(
{:_,:_,:_},
true,
[:local]
)

#Tell BEAM to trace this processs, but send the result to the simple tracer

:erlang.trace(self(),
true,
[:send,
:receive,
:procs,
:ports,
:garbage_collection,
:monotonic_timestamp,
:set_on_first_spawn,
:set_on_first_link,
:call,
:return_to,
{:tracer, simple},
:arity])

IO.inspect Enum.map([1,2,3,4,5], fn x -> :math.sqrt(x) end)

#Tell BEAM to stop tracing 
:erlang.trace(self(), false, [:all])

#This should not show up in the trace

IO.inspect Enum.map([3,7,11,101], fn x -> :math.sqrt(x) end)

#Tell BEAM to start tracing again

:erlang.trace(self(),
true,
[:send,
:receive,
:procs,
:ports,
:garbage_collection,
:monotonic_timestamp,
:set_on_first_spawn,
:set_on_first_link,
:call,
:return_to,
{:tracer, fancy},
:arity])


IO.inspect Enum.map([10,20,30,40,50], fn x -> :math.sqrt(x) end)

该程序使用两个单独的进程来跟踪主要进程。或至少它试图。这是我运行时获得的输出:

[ericu-destroyer-of-worlds] ~$ elixir ~/elixir_tracing.ex 
[1.0, 1.4142135623730951, 1.7320508075688772, 2.0, 2.23606797749979]
{:trace_ts, #PID<0.71.0>, :call, {Enum, :map, 2}, -576460751827716034}
Segmentation fault

我可以告诉:erlang.trace(self(), false, [:all])的调用会导致分段错误。我要做的就是禁用所有跟踪,以便进程simple停止接收跟踪。

更新

一位意见提供者表示他们无法重现崩溃。

我在以下版本上尝试了上面的代码,崩溃了

Erlang/OTP 19 [erts-8.0] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]

Elixir 1.3.1

然后我在这个版本上运行它并且没有崩溃

Erlang/OTP 18 [erts-7.3.1] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]

Elixir 1.2.5

为什么这个代码会在一个版本而不是另一个版本上崩溃?

0 个答案:

没有答案