Drop Handler
Because DTrace uses fixed-size buffers in the kernel and the mechanism for transferring data from these buffers is driven by the consumer, the system is designed to drop data when there is no space in the buffers. The DTrace framework has a mechanism to inform the consumer about how much data is dropped and why the data is being dropped.
By default, the libdtrace
library aborts the process when the consumer is informed about data drop. You can see this behavior if you run a simple consumer by using the following D program:
#pragma D option dynvarsize=1k syscall:::entry { self->ts = timestamp; } syscall:::return /self->ts/ { @c[probefunc] = avg(timestamp - self->ts); self->ts = 0; }
By setting the dynvarsize
tunable to a small value, you can guarantee that the program runs out of dynamic variable space while the program is executing. The following consumer does not implement a drop
handler:
# ./consumer-no-drophandler
processing aborted: Abort due to drop
#
The dtrace_handle_drop
() interface provided by the libdtrace
library specifies a drop handler.
The arguments to the dtrace_handle_drop
() function are:
-
DTrace handle
-
Pointer to a function to handle the drop
-
Pointer to a private argument to be passed to the drop handler
The dtrace_handle_drop
() function takes two arguments: a pointer to the dtrace_dropdata
data structure and a pointer to the private argument originally passed to the dtrace_handle_drop
() function. It returns one of two values: DTRACE_HANDLE_ABORT
or DTRACE_HANDLE_OK
.
The dtrace_dropdata
data structure contains information about the data drop since the last time the handler was called.
typedef struct dtrace_dropdata { dtrace_hdl_t *dtdda_handle; /* handle to DTrace library */ processorid_t dtdda_cpu; /* CPU, if any */ dtrace_dropkind_t dtdda_kind; /* kind of drop */ uint64_t dtdda_drops; /* number of drops */ uint64_t dtdda_total; /* total drops */ const char *dtdda_msg; /* preconstructed message */ } dtrace_dropdata_t;
The drop
handler has access to the following information:
-
DTrace handle
-
CPU on which the drops occur
-
Number and kind of drop for the call, including the total number
-
Predefined message
A simple drop handler returns DTRACE_HANDLE_OK
to ignore all data drops. However, the following example alerts the person running the D program about the data drop by printing a predefined message.
static int drophandler(const dtrace_dropdata_t *dropdata, void *arg) { fprintf(stderr, "%s", dropdata->dtdda_msg); return (DTRACE_HANDLE_OK); }
The output of example consumer would appear similar to the following when using this drop handler:
# ./consumer-drophandler
255 dynamic variable drops with non-empty dirty list
417 dynamic variable drops with non-empty dirty list
385 dynamic variable drops with non-empty dirty list
407 dynamic variable drops with non-empty dirty list
428 dynamic variable drops with non-empty dirty list
417 dynamic variable drops with non-empty dirty list
2 dynamic variable drops
447 dynamic variable drops with non-empty dirty list
431 dynamic variable drops with non-empty dirty list
440 dynamic variable drops with non-empty dirty list
29 dynamic variable drops
497 dynamic variable drops with non-empty dirty list
273 dynamic variable drops with non-empty dirty list
getpid 1633
sysconfig 1651
p_online 1977
gtime 2279
pset 2924
clock_gettime 3046
[ ... ]
A more sophisticated drop handler might choose to terminate processing under certain conditions. A consumer might choose to terminate under the following conditions:
-
Number of drops exceeds a threshold within a certain period.
-
Total number of drops exceeds a certain threshold, only upon seeing the drops from a particular CPU, or only upon seeing certain types of drops.
For example, a process aborts on seeing the aggregation drops but not on seeing the dynamic variable drops.