The software described in this documentation is either in Extended Support or Sustaining Support. See https://www.oracle.com/us/support/library/enterprise-linux-support-policies-069172.pdf for more information.
Oracle recommends that you upgrade the software described by this documentation as soon as possible.
The speculative tracing facility in DTrace allows you to tentatively trace data and then later decide whether to commit the data to a tracing buffer or discard the data. Predicates are the primary mechanism for filtering out uninteresting events. Predicates are useful when you know at the time that a probe fires whether or not the probe event is of interest. However, in some situations, you might not know whether a probe event is of interest until after the probe fires.
For example, if a system call is occasionally failing with an
error code in errno
, you might want to
examine the code path leading to the error condition. You can
write trace data at one or more probe locations to speculative
buffers, and then choose which data to commit to the principal
buffer at another probe location. As a result, your trace data
contains only the output of interest, no post-processing is
required, and the DTrace overhead is minimized.
To create a speculative buffer, use the
speculation()
function. This function returns
a speculation identifier, which you use in subsequent calls to
the speculate()
function.
Call the speculate()
function before
performing any data-recording actions in a clause. DTrace
directs all subsequent data that you record in a clause to the
speculative buffer. You can create only one speculation in any
given clause.
Typically, you assign a speculation identifier to a thread-local
variable, and then use that variable as a predicate to other
probes as well as an argument to speculate()
.
For example:
#!/usr/sbin/dtrace -Fs syscall::open:entry { /* * The call to speculation() creates a new speculation. If this fails, * dtrace will generate an error message indicating the reason for * the failed speculation(), but subsequent speculative tracing will be * silently discarded. */ self->spec = speculation(); speculate(self->spec); /* * Because this printf() follows the speculate(), it is being * speculatively traced; it will only appear in the data buffer if the * speculation is subsequently commited. */ printf("%s", copyinstr(arg0)); } syscall::open:return /self->spec/ { /* * To balance the output with the -F option, we want to be sure that * every entry has a matching return. Because we speculated the * open entry above, we want to also speculate the open return. * This is also a convenient time to trace the errno value. */ speculate(self->spec); trace(errno); }
If a speculative buffer contains data that you want to retain,
use the commit()
function to copy its
contents to the principal buffer. If you want to delete the
contents of a speculative buffer, use the
discard()
function. The following example
clauses commit or discard the speculative buffer based on the
value of the errno
variable:
syscall::open:return /self->spec && errno != 0/ { /* * If errno is non-zero, we want to commit the speculation. */ commit(self->spec); self->spec = 0; } syscall::open:return /self->spec && errno == 0/ { /* * If errno is not set, we discard the speculation. */ discard(self->spec); self->spec = 0; }
Running this script produces output similar to the following
example when the open()
system call fails:
# ./specopen.d
dtrace: script ’./specopen.d’ matched 4 probes
CPU FUNCTION
1 => open /var/ld/ld.config
1 <= open 2
1 => open /images/UnorderedList16.gif
1 <= open 4
...