From a0fd44f83d21cce3af1238edbfbe12b5987617e1 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 6 Nov 2017 16:25:42 +0000 Subject: bus/containers: Give each instance a list of all its connections Reviewed-by: Philip Withnall [smcv: Fix minor conflict] Signed-off-by: Simon McVittie Bug: https://bugs.freedesktop.org/show_bug.cgi?id=101354 --- bus/containers.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/bus/containers.c b/bus/containers.c index e30feb37..91806dbe 100644 --- a/bus/containers.c +++ b/bus/containers.c @@ -55,6 +55,9 @@ typedef struct BusContainers *containers; DBusServer *server; DBusConnection *creator; + /* List of owned DBusConnection, removed when the DBusConnection is + * removed from the bus */ + DBusList *connections; unsigned long uid; } BusContainerInstance; @@ -219,6 +222,11 @@ bus_container_instance_unref (BusContainerInstance *self) * BusContainerInstance */ _dbus_assert (self->server == NULL); + /* Similarly, as long as there are connections, the BusContainerInstance + * can't be freed, because each connection holds a reference to the + * BusContainerInstance */ + _dbus_assert (self->connections == NULL); + creator_data = dbus_connection_get_data (self->creator, container_creator_data_slot); _dbus_assert (creator_data != NULL); @@ -376,6 +384,11 @@ bus_container_instance_lost_connection (BusContainerInstance *instance, bus_container_instance_ref (instance); dbus_connection_ref (connection); + /* This is O(n), but we don't expect to have many connections per + * container instance. */ + if (_dbus_list_remove (&instance->connections, connection)) + dbus_connection_unref (connection); + dbus_connection_set_data (connection, contained_data_slot, NULL, NULL); dbus_connection_unref (connection); @@ -398,6 +411,16 @@ new_connection_cb (DBusServer *server, return; } + if (_dbus_list_append (&instance->connections, new_connection)) + { + dbus_connection_ref (new_connection); + } + else + { + bus_container_instance_lost_connection (instance, new_connection); + return; + } + /* If this fails it logs a warning, so we don't need to do that. * We don't know how to undo this, so do it last (apart from things that * cannot fail) */ @@ -819,6 +842,7 @@ bus_containers_remove_connection (BusContainers *self, { #ifdef DBUS_ENABLE_CONTAINERS BusContainerCreatorData *creator_data; + BusContainerInstance *instance; dbus_connection_ref (connection); creator_data = dbus_connection_get_data (connection, @@ -833,7 +857,7 @@ bus_containers_remove_connection (BusContainers *self, iter != NULL; iter = next) { - BusContainerInstance *instance = iter->data; + instance = iter->data; /* Remember where we got to before we do something that might free * iter and instance */ @@ -847,6 +871,18 @@ bus_containers_remove_connection (BusContainers *self, } } + instance = dbus_connection_get_data (connection, contained_data_slot); + + if (instance != NULL) + { + bus_container_instance_ref (instance); + + if (_dbus_list_remove (&instance->connections, connection)) + dbus_connection_unref (connection); + + bus_container_instance_unref (instance); + } + dbus_connection_unref (connection); #endif /* DBUS_ENABLE_CONTAINERS */ } -- cgit v1.2.3