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.