|
Description
|
The buffered output handler makes a callback with invalid data (zero) under the following condiitions:
- multiple aggregations are passed to printa()
- format string places values ahead of the tuple
BEGIN
{
@a[1] = sum(1);
@b[1] = sum(2);
@a[2] = sum(3);
printa("[%d] %@d %@d\n", @a, @b);
exit(0);
}
The above generates the expected callbacks from the buffered output handler:
0 1 :BEGIN [1] 1 2
[2] 3 0
However, if I change the printa format string so the tuple comes last:
printa("%@d %@d [%d]\n", @a, @b);
then every callback with the AGGKEY flag set has a record value of zero, although the buffered output remains correct. Also, the current record does not exist in the current aggdata. That is, (dtbda_recdesc != &dtbda_aggdata->dtada_desc->dtagd_rec[i]) at any index i in the range (1 .. dtbda_aggdata->dtada_desc->dtagd_nrecs - 1).
Unfortunately, this behavior can't be demonstrated with the new dtrace(1M) -B option:
dtrace: dtrace_bufdata:
dtrace: dtbda_buffered => "1"
dtrace: dtbda_probe => <NULL>
dtrace: dtbda_aggdata => <non-NULL>
dtrace: dtbda_recdesc => <non-NULL>
dtrace: dtbda_flags => 0x1 (AGGKEY)
...
dtrace: dtrace_recdesc:
dtrace: dtrd_action => 1
dtrace: dtrd_size => 4
dtrace: dtrd_offset => 16
...
What would help here is the dereferenced value of (dtbda_aggdata->dtada_data + dtbda_recdesc->dtrd_offset) under the "dtrace_recdesc" header so it is possible to verify that the record value matches dtbda_buffered (in this case, 0 does not match "1"). Also, after
dtrace: dtrace_aggdesc:
dtrace: dtagd_name => "b"
dtrace: dtagd_varid => 2
dtrace: dtagd_id => 2
dtrace: dtagd_nrecs => 3
it would help to display the index of the current record (in this case 3, the value of dtagd_nrecs), obtained
for (r = 1; r < aggdesc->dtagd_nrecs; ++r) {
if (&aggdesc->dtagd_rec[r] == rec) {
break;
}
}
|