Discussion:
SD-Bus: Possible bug / lack of documentation causing memory leak (at exit?)
(too old to reply)
Pauli Sundberg
2017-12-19 12:23:45 UTC
Permalink
Hi!

I stumbled upon a memory leak with attached silly test program (attached
below), and while doing some testing i found out that i need to call the
'sd_bus_process' after
'sd_bus_release_name' to avoid memory leak

The leak shows up with valgrind, and looks like
==18842== 3,402 (1,800 direct, 1,602 indirect) bytes in 1 blocks are
definitely lost in loss record 11 of 12
==18842== at 0x4C31B25: calloc (in /usr/lib/valgrind/vgpreload_
memcheck-amd64-linux.so)
==18842== by 0x4E8AC2F: sd_bus_new (sd-bus.c:177)
==18842== by 0x4E8E5C1: sd_bus_open_user (sd-bus.c:1138)
==18842== by 0x108D47: Component::dbus_open() (in /XXX/sdtest)
==18842== by 0x108BCC: main (in /XXX/sdtest)


On the appendix there is the 'FIXME' marker with line that makes the memory
leak go away.

Is this lack of documentation or a bug? I found the issue with stock ubuntu
17.04 version - 234-2ubuntu12.1 -- and recompiled current git head
82a18dcfb23fe5f259a2eb555fb90e3a3475f12d and the issue seems to be in both
versions.

I was about to do man-page pull request, but started to hesitate, since the
code in the release looks like such that it would handle some messaging.


Cheers,
Pauli




=== Appendix A: test program ===

#include <stdio.h>
#include <stdlib.h>
#include <systemd/sd-bus.h>
#include <assert.h>

class Component
{
public:
Component( const char* name ) : dbus( NULL )
{
this->name = name;
}


~Component()
{
if ( this->dbus )
{
printf("Destructor called!\n");
assert( sd_bus_release_name( dbus, this->name ) >= 0 );

loop(); // FIXME: Commenting this makes it leak memory
sd_bus_flush(dbus);
sd_bus_unref(dbus);
}
}


bool loop()
{
for ( ;; )
{
int ret = sd_bus_process( dbus, NULL);
assert ( ret >= 0 );

if ( ret > 0 )
continue;

break;
}
return true;
}

bool dbus_open()
{
int r;
r = sd_bus_open_user(&dbus);
if (r < 0)
{
printf( "Failed to connect to system bus: %s\n", strerror(-r) );
return false;
}


// Take a well-known service name so that clients can find us
r = sd_bus_request_name(dbus, this->name , 0);
if (r < 0)
{
printf("Failed to acquire service name: %s\n", strerror(-r));
return false;
}

return true;
}

private:
sd_bus* dbus;
const char* name;
};


int main()
{
Component com{ "com.example.foobar" };
printf("Hello there!\n");
com.dbus_open();
com.loop();
printf("Bye then!\n");
}

Loading...