Memory leak when opening a dbus proxy?

Hi,

There should be something wrong with my code but I can’t see what.

When running this code, I can see that the memory of my application is increasing endlessly and I can’t see why.

#include <stdio.h>
#include <stdlib.h>
#include <gio/gio.h>

int main(void) {
	unsigned int tmp = 1000000;
	puts("!!!Hello World!!!");

	GError *error = NULL;
	GDBusConnection *conn = NULL;
	GDBusProxy *proxy = NULL;

	while (tmp--) {
		conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
		if (!conn) {
			g_printerr("g_bus_get_sync failed: %s\n", error->message);
			g_clear_error(&error);
			return EXIT_SUCCESS;
		}

		proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
		NULL, /* GDBusInterfaceInfo */
		"org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus",
				NULL, &error);
		if (!proxy) {
			g_printerr("g_dbus_proxy_new_sync failed: %s\n", error->message);
			g_clear_error(&error);
			g_object_unref(conn);
			return EXIT_SUCCESS;
		}

		g_object_unref(proxy);
		g_object_unref(conn);

//		while (g_main_context_pending(NULL))
//		    g_main_context_iteration(NULL, TRUE);
	}
	return EXIT_SUCCESS;
}

In another thread similar to mine, one reply was asking to add the commented lines while (g_main_context_pending(…))...

Indeed it improves as the memory increases slower but unfortunately still increases.

By the way, my understanding is that, with calls to _sync function, these commented lines should not be needed.

I agree my code does not make sense, but it was just to isolate an issue I see on a bigger code where I call methods.

gautier@PO-SPEC-99:~/eclipse-workspace/test-dbus/Debug$ ./test-dbus &
[1] 133145
gautier@PO-SPEC-99:~/eclipse-workspace/test-dbus/Debug$ !!!Hello World!!!

gautier@PO-SPEC-99:~/eclipse-workspace/test-dbus/Debug$ cat /proc/133145/status | grep -B 1 -A 4 VmSize
VmPeak:	  221796 kB
VmSize:	  184448 kB
VmLck:	       0 kB
VmPin:	       0 kB
VmHWM:	   31640 kB
VmRSS:	   31640 kB
gautier@PO-SPEC-99:~/eclipse-workspace/test-dbus/Debug$ cat /proc/133145/status | grep -B 1 -A 4 VmSize
VmPeak:	  266044 kB
VmSize:	  266044 kB
VmLck:	       0 kB
VmPin:	       0 kB
VmHWM:	  113128 kB
VmRSS:	  113128 kB
gautier@PO-SPEC-99:~/eclipse-workspace/test-dbus/Debug$ cat /proc/133145/status | grep -B 1 -A 4 VmSize
VmPeak:	  399700 kB
VmSize:	  399700 kB
VmLck:	       0 kB
VmPin:	       0 kB
VmHWM:	  247200 kB
VmRSS:	  247200 kB
gautier@PO-SPEC-99:~/eclipse-workspace/test-dbus/Debug$ cat /proc/133145/status | grep -B 1 -A 4 VmSize
VmPeak:	  493816 kB
VmSize:	  493816 kB
VmLck:	       0 kB
VmPin:	       0 kB
VmHWM:	  341712 kB
VmRSS:	  341712 kB
gautier@PO-SPEC-99:~/eclipse-workspace/test-dbus/Debug$ cat /proc/133145/status | grep -B 1 -A 4 VmSize
VmPeak:	  641804 kB
VmSize:	  641804 kB
VmLck:	       0 kB
VmPin:	       0 kB
VmHWM:	  489972 kB
VmRSS:	  489972 kB

If you think you have a leak, your first step should be to run your program under valgrind or with asan or msan enabled.

Thanks for your reply.

I did it and found this (see bottom)

So it looks like there is some memory issues. Are they leaks, I don’t know.

But the aim of my question was more to get a feedback if there was something wrong with my code as I am not familiar with glib.

And my main worry is that a similar code is called from a process which never ends, so after a while, the oom-killer is killing my process. And now, I am trying to find an understanding of what is happening and a fix (if any).


valgrind with massif tool

--------------------------------------------------------------------------------
Command:            ./test-dbus
Massif arguments:   --time-unit=ms
ms_print arguments: massif.out.153601
--------------------------------------------------------------------------------


    MB
87.41^                                                                       #
     |                                                                   @@@@#
     |                                                                @@@@@@@#
     |                                                           @@@@@@@ @@@@#
     |                                                           @ @@ @@ @@@@#
     |                                                         @@@ @@ @@ @@@@#
     |                                                    @@@@@@@@ @@ @@ @@@@#
     |                                                 @@@@@@ @@@@ @@ @@ @@@@#
     |                                              @@@@ @@@@ @@@@ @@ @@ @@@@#
     |                                        @@@@@@@@@@ @@@@ @@@@ @@ @@ @@@@#
     |                                    @@@@@@ @@ @@@@ @@@@ @@@@ @@ @@ @@@@#
     |                               @@@@@@@@ @@ @@ @@@@ @@@@ @@@@ @@ @@ @@@@#
     |                             @@@ @@ @@@ @@ @@ @@@@ @@@@ @@@@ @@ @@ @@@@#
     |                         @@@@@@@ @@ @@@ @@ @@ @@@@ @@@@ @@@@ @@ @@ @@@@#
     |                     @@@@@ @ @@@ @@ @@@ @@ @@ @@@@ @@@@ @@@@ @@ @@ @@@@#
     |                 @@@@@@@ @ @ @@@ @@ @@@ @@ @@ @@@@ @@@@ @@@@ @@ @@ @@@@#
     |             @@@@@@@ @@@ @ @ @@@ @@ @@@ @@ @@ @@@@ @@@@ @@@@ @@ @@ @@@@#
     |         @@@@@ @ @@@ @@@ @ @ @@@ @@ @@@ @@ @@ @@@@ @@@@ @@@@ @@ @@ @@@@#
     |      @@@@@ @@ @ @@@ @@@ @ @ @@@ @@ @@@ @@ @@ @@@@ @@@@ @@@@ @@ @@ @@@@#
     |   @@@@ @@@ @@ @ @@@ @@@ @ @ @@@ @@ @@@ @@ @@ @@@@ @@@@ @@@@ @@ @@ @@@@#
   0 +----------------------------------------------------------------------->s
     0                                                                   452.0

  • valgrind with memcheck tool
==158156== LEAK SUMMARY:
==158156==    definitely lost: 0 bytes in 0 blocks
==158156==    indirectly lost: 0 bytes in 0 blocks
==158156==      possibly lost: 640 bytes in 2 blocks
==158156==    still reachable: 73,130,064 bytes in 1,504,282 blocks
==158156==         suppressed: 0 bytes in 0 blocks

That’s a bit hard to say. :slight_smile: The code you pasted is obviously not the production code (and I’m not volunteering to review your production code). In general, though, the main things you should consider are:

  • Async code in GLib generally assumes that a main loop is running. While GDBus does have a worker thread for communicating with the D-Bus socket in the background, callbacks are sent to the main thread and if you’re not running the global default main loop then they’ll probably queue up indefinitely.
  • Calling D-Bus methods synchronously is generally a bad idea because they can take many seconds to give a reply; your application will be blocked from handling other events for that time unless you make the D-Bus call asynchronously.
  • Writing asynchronous code is something you have to do from the beginning; unfortunately C doesn’t have the syntax to allow you to easily convert synchronous code to asynchronous code at a later date.

See Asynchronous Programming - GNOME Developer Documentation , Main Contexts - GNOME Developer Documentation and Threading - GNOME Developer Documentation

1 Like

Thanks again for your answer and for the links

In the context of our application, sync calls are easier to implement and we don’t mind waiting for the answers. I am going to investigate a little bit on this issue. But if I can’t find any improvement, I will switch to async calls.