我一直在使用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
为什么这个代码会在一个版本而不是另一个版本上崩溃?