dagbay |
02-04-2018 03:29 AM |
How to fix libudev memory leaks
I'm implementing a libudev based monitoring code for USB devices under the hidraw driver. I've implemented the standard example from the web and checked for memory leaks with valgrind and gdb: /*******************************************
libudev example.
This example prints out properties of
each of the hidraw devices. It then
creates a monitor which will report when
hidraw devices are connected or removed
from the system.
This code is meant to be a teaching
resource. It can be used for anyone for
any reason, including embedding into
a commercial product.
The document describing this file, and
updated versions can be found at:
http://www.signal11.us/oss/udev/
Alan Ott
Signal 11 Software
2010-05-22 - Initial Revision
2010-05-27 - Monitoring initializaion
moved to before enumeration.
*******************************************/
.....
I was unhappy to find that some libudev functions that are not supposed to allocate memory are leaking. I traced this by exiting (after all objects are unreff'ed) at differrent points and looking at the valgrind report. Specifically This code leaks: int main (void)
{
struct udev *udev;
struct udev_enumerate *enumerate;
struct udev_list_entry *devices, *dev_list_entry;
struct udev_device *dev, *devParent;
struct udev_monitor *mon;
int fd;
/* Create the udev object */
udev = udev_new();
if (!udev)
{
printf("Can't create udev\n");
exit(1);
}
/* This section sets up a monitor which will report events when
blah blah....
"hidraw" devices. */
/* Set up a monitor to monitor hidraw devices */
mon = udev_monitor_new_from_netlink(udev, "udev");
udev_monitor_filter_add_match_subsystem_devtype(mon, "hidraw", NULL);
udev_monitor_enable_receiving(mon);
/* Get the file descriptor (fd) for the monitor.
This fd will get passed to select() */
fd = udev_monitor_get_fd(mon);
/* Create a list of the devices in the 'hidraw' subsystem. */
enumerate = udev_enumerate_new(udev);
udev_enumerate_add_match_subsystem(enumerate, "hidraw");
if (1)
{
// leak debug block, unref of all allocated objects and exit.
udev_enumerate_unref(enumerate);
udev_monitor_unref(mon);
udev_unref(udev);
return 0;
}
udev_enumerate_scan_devices(enumerate);
devices = udev_enumerate_get_list_entry(enumerate);
/* For each item enumerated, print out its information.
The fiest line that leaks is: udev_enumerate_add_match_subsystem(enumerate, "hidraw"); Here is valgind report: ==20471== HEAP SUMMARY:
==20471== in use at exit: 4,096 bytes in 1 blocks
==20471== total heap usage: 11 allocs, 10 frees, 28,086 bytes allocated
==20471==
==20471== 4,096 bytes in 1 blocks are still reachable in loss record 1 of 1
==20471== at 0x482E27C: malloc (vg_replace_malloc.c:299)
==20471== by 0x48624DA: ??? (in /lib/i386-linux-gnu/libudev.so.1.6.5)
==20471== by 0x486A742: ??? (in /lib/i386-linux-gnu/libudev.so.1.6.5)
==20471== by 0x108BAA: main (in /home/pi/projects/eclipse/testUSB/udevHidraw)
==20471==
==20471== LEAK SUMMARY:
==20471== definitely lost: 0 bytes in 0 blocks
==20471== indirectly lost: 0 bytes in 0 blocks
==20471== possibly lost: 0 bytes in 0 blocks
==20471== still reachable: 4,096 bytes in 1 blocks
==20471== suppressed: 0 bytes in 0 blocks
If the "leak debug block" is placed before that line valgrind is happy reporting no memory leaks.
The further down the example code that the "leak debug block" is moved the worse the memory leaks become.
This issue is of concern because my code needs to run over years and such leaks can accumulate unchecked.
Any suggestions why it happens and how to keep it under control?
|