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?