ustack() Action
Tracing a process thread's stack at the time a particular probe is activated
is often useful for examining a problem in more detail. The ustack() action traces
the user thread's stack. If, for example, a process that opens many files
occasionally fails in the open(2) 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 which takes
the value of the first operand specified on the dtrace(1M) 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 and
dtrace(1M) resolves those PC values to symbol names by looking though the process's
symbol tables. If dtrace can't resolve the PC value to a symbol,
it will print out the value as a hexadecimal integer.
If a process exits or is killed before the ustack() data is formatted
for output, dtrace might be unable to convert the PC values in the
stack trace to symbol names, and will be forced to display them as
hexadecimal integers. To work around this limitation, specify a process of interest with
the -c or -p option to dtrace. See Chapter 14, dtrace(1M) Utility for details on these
and other options. 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:
/*
* 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;
}
The above script stops a process just before it exits if the
ustack() action has been applied to a thread in that process. This
technique ensures that the dtrace command will be able to resolve the PC values
to symbolic names. Notice that the value of stop_pids[pid] is set to 0
after it has been used to clear the dynamic variable. Remember to set
stopped processes running again using the prun(1) command or your system will accumulate many
stopped processes.