bus/containers: Give each instance a list of all its connections

Reviewed-by: Philip Withnall <withnall@endlessm.com>
[smcv: Fix minor conflict]
Signed-off-by: Simon McVittie <smcv@collabora.com>
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=101354
This commit is contained in:
Simon McVittie 2017-11-06 16:25:42 +00:00
parent 3048c90ccb
commit d5ff91ff9a

View file

@ -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 */
}