summaryrefslogtreecommitdiff
path: root/src/nm-exported-object.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nm-exported-object.c')
-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);
}