summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-09-17 17:13:30 +0200
committerThomas Haller <thaller@redhat.com>2015-09-18 18:01:55 +0200
commit45f682e22225ccff745d2688d4475b7a0f23a210 (patch)
tree932ad7d42ec1a6e88b0af63c1b508b16955d1f06
parent24dc78957f082b12637b22bd1e5f803c7657af44 (diff)
downloadNetworkManager-45f682e22225ccff745d2688d4475b7a0f23a210.tar.gz
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.
-rw-r--r--src/nm-exported-object.c70
1 files changed, 59 insertions, 11 deletions
diff --git a/src/nm-exported-object.c b/src/nm-exported-object.c
index aec73e3ade..bdf409ad17 100644
--- a/src/nm-exported-object.c
+++ b/src/nm-exported-object.c
@@ -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);
}