Solaris 動的トレースガイド

ustack() アクション

問題をより詳しく調査するときは、特定のプローブが起動したときのプロセススレッドのスタックをトレースするとよいでしょう。ustack() アクションは、ユーザースレッドのスタックをトレースします。たとえば、多数のファイルを開くプロセスがあるとします。このプロセスは、ときどき open(2) システムコールに失敗します。この場合、問題のある open() を実行するコードパスを探すには、ustack() アクションを使用します。

syscall::open:entry
/pid == $1/
{
	self->path = copyinstr(arg0);
}

syscall::open:return
/self->path != NULL && arg1 == -1/
{
	printf("open for '%s' failed", self->path);
	ustack();
}

このスクリプトでは、マクロ変数 $1 も使用されています。このマクロ変数には、dtrace(1M) コマンド行で指定された最初のオペランドの値が入ります。


# dtrace -s ./badopen.d 31337
dtrace: script './badopen.d' matched 2 probes
CPU     ID                    FUNCTION:NAME
  0     40                      open:return open for '/usr/lib/foo' failed
              libc.so.1`__open+0x4
              libc.so.1`open+0x6c
              420b0
              tcsh`dosource+0xe0
              tcsh`execute+0x978
              tcsh`execute+0xba0
              tcsh`process+0x50c
              tcsh`main+0x1d54
              tcsh`_start+0xdc

ustack() アクションによって、スタックのプログラムカウンタ (PC) の値が記録されます。すると、dtrace(1M) により、プロセスのシンボルテーブルが検索され、PC 値がシンボル名に解決されます。dtrace が PC 値をシンボル名に解決できない場合は、その値は 16 進整数として出力されます。

ustack() データの出力書式が設定される前にプロセスが終了 (強制終了も含む) すると、dtrace が、スタックトレース内の PC 値をシンボル名に変換できない場合があります。この場合、これらの値は 16 進整数で表示されます。この制限を回避するには、-dtrace コマンドの -c オプションや p オプションを使って、対象プロセスを指定します。これらのオプションやその他のオプションの詳細については、第 14 章dtrace(1M) ユーティリティーを参照してください。プロセス ID やコマンドがあらかじめわかっていない場合は、次のような D プログラムで制限を回避できます。

/*
 * This example uses the open(2) system call probe, but this technique
 * is applicable to any script using the ustack() action where the stack
 * being traced is in a process that may exit soon.
 */
 syscall::open:entry
{
	ustack();
	stop_pids[pid] = 1;
}

syscall::rexit:entry
/stop_pids[pid] != 0/
{
	printf("stopping pid %d", pid);
	stop();
	stop_pids[pid] = 0;
}

このスクリプトは、プロセス内のスレッドに ustack() アクションが適用されている場合、プロセスを、その終了直前に停止します。この方法を利用すれば、dtrace コマンドで PC 値をシンボル名に解決できます。stop_pids[pid] の値は、動的変数の消去が完了したら、ゼロになります。prun(1) コマンドを使って、停止したプロセスが実行再開するように設定してください。そうしないと、システム上の停止プロセスが蓄積されてしまいます。