exported-object: explicitly disconnect bindings and signal handlers to GDBusInterfaceSkeleton interfaces

While an NMExportedObject is exported (i.e. registered at NMBusManager),
it has a list of GDBusInterfaceSkeleton interfaces. The properties of
the nm-object are bound to the interfaces and the signals connected.

Previously, when unexporting the NMExportedObject, we would only unref
the interfaces, but not explicitly disconnect. As there is no guarantee
that the lifetime of the interfaces is shorter then the lifetime of the
nm-object, hence, explicitly disconnect.
This commit is contained in:
Thomas Haller
2015-09-17 17:13:30 +02:00
parent 24dc78957f
commit 45f682e222

View File

@@ -353,6 +353,14 @@ nm_exported_object_meta_marshal (GClosure *closure, GValue *return_value,
g_free (local_param_values);
}
GQuark _skeleton_data_quark (void);
G_DEFINE_QUARK (skeleton-data, _skeleton_data);
typedef struct {
GBinding **prop_bindings;
gulong *method_signals;
} SkeletonData;
static void
nm_exported_object_create_skeletons (NMExportedObject *self,
GType object_type)
@@ -372,16 +380,22 @@ nm_exported_object_create_skeletons (NMExportedObject *self,
for (iter = classinfo->skeleton_types; iter; iter = iter->next) {
GType dbus_skeleton_type = GPOINTER_TO_SIZE (iter->data);
gs_free GParamSpec **properties = NULL;
SkeletonData *skeleton_data;
guint j;
interface = G_DBUS_INTERFACE_SKELETON (g_object_new (dbus_skeleton_type, NULL));
priv->interfaces = g_slist_prepend (priv->interfaces, interface);
skeleton_data = g_slice_new (SkeletonData);
/* Bind properties */
properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (interface), &n_properties);
for (i = 0; i < n_properties; i++) {
skeleton_data->prop_bindings = g_new (GBinding *, n_properties + 1);
for (i = 0, j = 0; i < n_properties; i++) {
GParamSpec *nm_property;
GBindingFlags flags;
GBinding *prop_binding;
nm_property = g_object_class_find_property (object_class, properties[i]->name);
if (!nm_property)
@@ -391,23 +405,61 @@ nm_exported_object_create_skeletons (NMExportedObject *self,
if ( (nm_property->flags & G_PARAM_WRITABLE)
&& !(nm_property->flags & G_PARAM_CONSTRUCT_ONLY))
flags |= G_BINDING_BIDIRECTIONAL;
g_object_bind_property (self, properties[i]->name,
interface, properties[i]->name,
flags);
prop_binding = g_object_bind_property (self, properties[i]->name,
interface, properties[i]->name,
flags);
if (prop_binding)
skeleton_data->prop_bindings[j++] = prop_binding;
}
skeleton_data->prop_bindings[j++] = NULL;
/* Bind methods */
for (i = 0; i < classinfo->methods->len; i++) {
skeleton_data->method_signals = g_new (gulong, classinfo->methods->len + 1);
for (i = 0, j = 0; i < classinfo->methods->len; i++) {
NMExportedObjectDBusMethodImpl *method = &g_array_index (classinfo->methods, NMExportedObjectDBusMethodImpl, i);
GClosure *closure;
gulong method_signal;
if (method->dbus_skeleton_type != dbus_skeleton_type)
continue;
closure = g_cclosure_new_swap (method->impl, self, NULL);
g_closure_set_meta_marshal (closure, NULL, nm_exported_object_meta_marshal);
g_signal_connect_closure (interface, method->method_name, closure, FALSE);
method_signal = g_signal_connect_closure (interface, method->method_name, closure, FALSE);
if (method_signal != 0)
skeleton_data->method_signals[j++] = method_signal;
}
skeleton_data->method_signals[j++] = 0;
g_object_set_qdata ((GObject *) interface, _skeleton_data_quark (), skeleton_data);
}
}
static void
nm_exported_object_destroy_skeletons (NMExportedObject *self)
{
NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
g_return_if_fail (priv->interfaces);
while (priv->interfaces) {
gs_unref_object GDBusInterfaceSkeleton *interface = G_DBUS_INTERFACE_SKELETON (priv->interfaces->data);
SkeletonData *skeleton_data;
guint j;
priv->interfaces = g_slist_remove (priv->interfaces, interface);
skeleton_data = g_object_steal_qdata ((GObject *) interface, _skeleton_data_quark ());
for (j = 0; skeleton_data->prop_bindings[j]; j++)
g_object_unref (skeleton_data->prop_bindings[j]);
for (j = 0; skeleton_data->method_signals[j]; j++)
g_signal_handler_disconnect (interface, skeleton_data->method_signals[j]);
g_free (skeleton_data->prop_bindings);
g_free (skeleton_data->method_signals);
g_slice_free (SkeletonData, skeleton_data);
}
}
@@ -527,8 +579,7 @@ nm_exported_object_unexport (NMExportedObject *self)
nm_bus_manager_unregister_object (priv->bus_mgr, self);
g_slist_free_full (priv->interfaces, g_object_unref);
priv->interfaces = NULL;
nm_exported_object_destroy_skeletons (self);
g_clear_pointer (&priv->path, g_free);
g_clear_object (&priv->bus_mgr);
@@ -691,9 +742,6 @@ nm_exported_object_dispose (GObject *object)
g_variant_builder_clear (&priv->pending_notifies);
nm_clear_g_source (&priv->notify_idle_id);
g_slist_free_full (priv->interfaces, g_object_unref);
priv->interfaces = NULL;
G_OBJECT_CLASS (nm_exported_object_parent_class)->dispose (object);
}