現在実行中のプロセスに erlang で seq_trace を設定できることを理解しています。しかし、シェル、または dbg トレースのようなリモート シェルから別のプロセスに設定するにはどうすればよいでしょうか?
1 に答える
を使用して、別のプロセスでシーケンシャル トレースを有効にできますdbg
。たとえばx
、エクスポートされたcall/2
関数を持つモジュールがあるとします。
call(Pid, Msg) ->
Pid ! {self(), Msg},
receive
{Pid, Reply} -> Reply
end.
この関数は、単純な呼び出し応答を実装します。y
また、ループ受信機能を持つモジュールがあるとしましょう:
loop() ->
receive
{Pid, Msg} ->
seq_trace:print({?MODULE, self(), Pid, Msg}),
Pid ! {self(), {Msg, os:timestamp()}};
_ -> ok
end,
?MODULE:loop().
この関数は、 から送信された形式のメッセージを予期し、x:call/2
それを受信すると、有効な場合は順次トレースにメッセージを出力し、タイムスタンプを付けて元のメッセージを発信者に送り返します。他のすべてのメッセージは無視されます。
また、シーケンシャル トレースを収集する関数も必要です。以下の再帰systracer/1
関数は、タプルをリストに収集し、要求されたときにメッセージseq_trace
のリストを生成します。seq_trace
systracer(Acc) ->
receive
{seq_trace,_,_,_}=S ->
systracer([S|Acc]);
{seq_trace,_,_}=S ->
systracer([S|Acc]);
{dump, Pid} ->
Pid ! lists:reverse(Acc),
systracer([]);
stop -> ok
end.
systracer/1
関数もモジュールからエクスポートされると仮定しましょうx
。
Erlang シェルを使用して、これをすべてセットアップしましょう。y:loop/0
まず、スポーンしてみましょうx:systracer/1
:
1> Y = spawn(y,loop,[]).
<0.36.0>
2> S = spawn(x,systracer,[[]]).
<0.38.0>
3> seq_trace:set_system_tracer(S).
false
生成後x:systracer/1
、プロセスをseq_trace
システム トレーサーとして設定します。次に、開始する必要がありますdbg
。
4> dbg:tracer(), dbg:p(all,call).
{ok,[{matched,nonode@nohost,28}]}
これらの呼び出しは非常に標準的ですが、特にデバッグ セッション中にトレースdbg
を使用する予定がある場合は、必要に応じて自由に変更できます。dbg
実際には、 でシーケンシャル トレースを有効にするときはdbg
、通常、関数の特定の引数をキー入力して行います。これにより、その関数のすべての呼び出しのトレースを取得することなく、特定の関数呼び出しに固有のトレースを取得できます。これらの線に沿って、 がアトムの値を持つ 2 番目の引数で呼び出されdbg:tpl/3
たときに、シーケンシャル トレース フラグをオンにするために使用します。まず、 を使用して適切な一致仕様を作成し、必要な順次トレース フラグを有効にしてから、次のように一致仕様を適用します。x:call/2
trace
dbg:fun2ms/1
dbg:tpl/3
5> Ms = dbg:fun2ms(fun([_,trace]) -> set_seq_token(send,true), set_seq_token('receive',true), set_seq_token(print,true) end).
[{['_',trace],
[],
[{set_seq_token,send,true},
{set_seq_token,'receive',true},
{set_seq_token,print,true}]}]
6> dbg:tpl(x,call,Ms).
{ok,[{matched,nonode@nohost,1},{saved,1}]}
x:call/2
これで、2 番目の引数を使用して呼び出して、trace
シーケンシャル トレースを発生させることができます。結果のトレースにシェル I/O 関連のメッセージが表示されないように、生成されたプロセスからこの呼び出しを行います。
7> spawn(fun() -> x:call(Y, trace), x:call(Y, foo) end).
(<0.46.0>) call x:call(<0.36.0>,trace)
<0.46.0>
出力の最初の行は、以前に指定したため、通常のdbg
トレースからdbg:p(all, call)
のものです。順次トレース結果を取得するには、systrace/1
プロセスからダンプを取得する必要があります。
8> S ! {dump, self()}.
{dump,<0.34.0>}
これにより、これまでに収集されたすべてのシーケンシャル トレースがシェル プロセスに送信されます。シェルflush()
コマンドを使用してそれらを表示できます。
9> flush().
Shell got [{seq_trace,0,{send,{0,1},<0.47.0>,<0.36.0>,{<0.47.0>,trace}}},
{seq_trace,0,{'receive',{0,1},<0.47.0>,<0.36.0>,{<0.47.0>,trace}}},
{seq_trace,0,{print,{1,2},<0.36.0>,[],{y,<0.36.0>,<0.47.0>,trace}}},
{seq_trace,0,
{send,{1,3},
<0.36.0>,<0.47.0>,
{<0.36.0>,{trace,{1423,709096,206121}}}}},
{seq_trace,0,
{'receive',{1,3},
<0.36.0>,<0.47.0>,
{<0.36.0>,{trace,{1423,709096,206121}}}}},
{seq_trace,0,{send,{3,4},<0.47.0>,<0.36.0>,{<0.47.0>,foo}}},
{seq_trace,0,{'receive',{3,4},<0.47.0>,<0.36.0>,{<0.47.0>,foo}}},
{seq_trace,0,{print,{4,5},<0.36.0>,[],{y,<0.36.0>,<0.47.0>,foo}}},
{seq_trace,0,
{send,{4,6},
<0.36.0>,<0.47.0>,
{<0.36.0>,{foo,{1423,709096,206322}}}}},
{seq_trace,0,
{'receive',{4,6},
<0.36.0>,<0.47.0>,
{<0.36.0>,{foo,{1423,709096,206322}}}}}]
案の定、これらは私たちが期待していたシーケンシャル トレース メッセージです。trace
最初に、 atomを含むメッセージの場合、 からの送信にx:call/2
続いて での受信y:loop/0
と の結果が得られseq_trace:print/1
、次にy:loop/0
から の呼び出し元への送信が行われx:call/2
ます。次に、x:call(Y,foo)
が同じプロセスで呼び出されるため、すべてのシーケンシャル トレース フラグがまだ有効であることを意味するため、シーケンシャル トレース メッセージの最初のセットの後に、x:call(Y,foo)
呼び出し用の同様のセットが続きます。
呼び出すだけでx:call(Y,foo)
、連続したトレース メッセージが表示されないことがわかります。
10> spawn(fun() -> x:call(Y, foo) end).
<0.55.0>
11> S ! {dump, self()}.
{dump,<0.34.0>}
12> flush().
Shell got []
これは、2 番目の引数x:call/2
が atom である場合にのみ、一致仕様が順次トレースを有効にするためtrace
です。
詳細については、seq_trace
およびdbg
man ページを参照してください。また、Erlang Run-Time System Application (ERTS) User's Guide の match specification の章もお読みください。