3

現在実行中のプロセスに erlang で seq_trace を設定できることを理解しています。しかし、シェル、または dbg トレースのようなリモート シェルから別のプロセスに設定するにはどうすればよいでしょうか?

4

1 に答える 1

3

を使用して、別のプロセスでシーケンシャル トレースを有効にできます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/2tracedbg:fun2ms/1dbg: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およびdbgman ページを参照してください。また、Erlang Run-Time System Application (ERTS) User's Guide の match specification の章もお読みください。

于 2015-02-12T03:16:29.197 に答える