Skip to content

libsysprof-capture: Clean ring buffer memory for counters

Apps using the collector API use sysprof_collector_set_counters() to report values of previously defined counters. The collector implements this report by populating a SysprofCaptureCounterSet struct.

However, sometimes we can observe completely random values in these counters. These random values are so wildly different that they make e.g. the charts in the Sysprof UI useless!

The SysprofCaptureCounterSet struct is rather interesting. It extends SysprofCaptureFrame, has a n_values counter, some extra padding, and the tail is 1+ SysprofCaptureCounterValues. Each SysprofCaptureCounterValues can contain up to 8 counter values.

Therefore when using sysprof_collector_set_counters(), the counters are grouped in packets of 8 id+value pairs. Let's look at a real example from a capture file generated from WebKit:

CTRSET frame at 520713
    group 0
        setting id 4 to 25,000000
        setting id 5 to 79,076893
        setting id 6 to 20,000000
        setting id 7 to 79,207139
        setting id 8 to 15,789474
        setting id 9 to 79,080517
        setting id 10 to 20,000000
        setting id 11 to 79,246893
    group 1
        setting id 12 to 25,000000
        setting id 13 to 79,091038
        setting id 14 to 23,809524
        setting id 15 to 79,123830
        setting id 16 to 21,052632
        setting id 17 to 79,189787
        setting id 18 to 20,000000
        setting id 19 to 79,234681
    group 2
        setting id 20 to 23,809524
        setting id 21 to 79,120228
        setting id 22 to 21,052632
        setting id 23 to 79,229608
        setting id 24 to 21,052632
        (empty)
        (empty)
        (empty)

Notice how, in the last group, the 3 last elements are empty.

Or at least, they were supposed to be empty. In my raw file, these last elements actually contain the following:

[...]
    group 2
        setting id 20 to 23,809524
        setting id 21 to 79,120228
        setting id 22 to 21,052632
        setting id 23 to 79,229608
        setting id 24 to 21,052632
        setting id 87955554 to 20445420015746541324787,0
        setting id 7479777 to 94327513216873524,054651321
        setting id 877 to 7213274321290062100443215432135745313213274321301700,01239997

That's because, in sysprof_collector_set_counters(), after requesting memory from the ring buffer, it merely copies the passed counter values to the groups. The function doesn't zero the remaining values. Thus what we see is previously written memory from the ring buffer.

Normally these bogus values are so bogus that their ids don't match any of the registered counter ids. In those cases Sysprof just ignores the values. However in some circumstances the ids can randomly match previously defined counter ids! This is when Sysprof accidentally shows the crazy values.

Fix that by memset()ing the groups to zero before copying the counters and values into them.

Merge request reports

Loading