The ustack() action traces the user thread's stack. If a process that opens many files occasionally fails in the open() system call, you can use the ustack() action to discover the code path that executes the failed open():
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(); }
This script also illustrates the use of the $1 macro variable. This macro variable takes the value of the first operand that is specified on the dtrace command line:
# 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 |
The ustack() action records program counter (PC) values for the stack. The dtrace command resolves those PC values to symbol names by looking though the process's symbol tables. The dtrace command prints out PC values that cannot be resolved as hexadecimal integers.
When a process exits or is killed before the ustack() data is formatted for output, the dtrace command might be unable to convert the PC values in the stack trace to symbol names. In that event the dtrace command displays these values as hexadecimal integers. To work around this limitation, specify a process of interest with the -c or -p option to dtrace. If the process ID or command is not known in advance, the following example D program that can be used to work around the limitation. The example uses the open system call probe, but this technique can be used with any script that uses the ustack action.
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; }
The previous script stops a process just before the process exits, if the ustack() action has been applied to a thread in that process. This technique ensures that the dtrace command can resolve the PC values to symbolic names. The value of stop_pids[pid] is set to 0 after clearing the dynamic variable.