Skip to content

GitLab

  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • D dbus
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 246
    • Issues 246
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 33
    • Merge requests 33
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Monitor
    • Monitor
    • Incidents
  • Packages & Registries
    • Packages & Registries
    • Container Registry
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • dbus
  • dbus
  • Issues
  • #326

Closed
Open
Created Jan 19, 2021 by xgsa@xgsa

Not canceled pending calls lead to memory leaks during dbus connection close

We have bumped into an issue, that Valgrind reports memory leaks in the case, when dbus_pending_call_set_notify registers a callback and dbus connection is shutdown before the reply arrives. Here is the minimized program, which reproduces the issue:

#include <cstdio>
#include <cstdlib>

#include <dbus/dbus.h>

void printf_and_exit(const char* error)
{
	printf(error);
	exit(EXIT_FAILURE);
}

int main(int argc, char **argv)
{
	DBusError error;
	dbus_error_init(&error);

	printf("Connecting...\n");
	DBusConnection *connection = dbus_bus_get_private(DBUS_BUS_SESSION, &error);
	if (!connection)
		printf_and_exit("ERROR: cannot initialize connection");
	dbus_connection_set_exit_on_disconnect(connection, false);

	printf("Creating a message for a method call...\n");
	DBusMessage *msg = dbus_message_new_method_call("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetId");
	if (!msg)
		printf_and_exit("ERROR: The message was not created\n");

	printf("Sending the message...\n");
	DBusPendingCall *pending_call = nullptr;
	if (!dbus_connection_send_with_reply(connection, msg, &pending_call, 10000))
		printf_and_exit("ERROR: The message was not sent\n");

	dbus_pending_call_set_notify(
    		pending_call,
    		[](DBusPendingCall*, void*) { printf(">> In callback!\n"); },
			nullptr,
			[](void*) { printf(">> In free function!\n"); }
	);

	printf("Flushing connection...\n");
	dbus_connection_flush(connection);

	// !!! Without canceling pending call, there are memory leaks in this program.
	// !!! With this line uncommented, no memory leaks are reported by Valgrind.
        // dbus_pending_call_cancel(pending_call);

	printf("Cleaning up...\n");
	dbus_pending_call_unref(pending_call);
	dbus_message_unref(msg);
	dbus_connection_close(connection);
	dbus_connection_unref(connection);

	dbus_error_free(&error);

	dbus_shutdown();

	return EXIT_SUCCESS;
}

Please, note that if dbus_pending_call_cancel is uncommented, no memory leaks are reported by Valgrind (checked on the latest master branch; valgrind reports for both of the cases with commented and uncommented line are attached).

Currently, we have to workaround the issue by gathering pending calls after dbus_pending_call_set_notify, removing them if callback is called and canceling all the gathered pending calls during connection shutdown. This seems not very optimal, but as far as I know, dbus does not provide a way to enumerate pending calls of the DBusConnection, whereas it tracks them.

The suggested solution is to cancel all the pending calls during connection close, which seems to be logical. I think, I could provide the patch implementing this if the issue is confirmed and the solution is considered as appropriate. So what do you think?

Assignee
Assign to
Time tracking