|
|
a85faa |
From 55afece5d291e692d3b54caa4e070f565c16e814 Mon Sep 17 00:00:00 2001
|
|
|
a85faa |
From: Thomas Haller <thaller@redhat.com>
|
|
|
a85faa |
Date: Wed, 31 Aug 2016 11:21:08 +0200
|
|
|
a85faa |
Subject: [PATCH 1/2] exported-object: fix source interface for
|
|
|
a85faa |
PropertiesChanged D-Bus signal
|
|
|
a85faa |
|
|
|
a85faa |
nm_exported_object_notify() hooks GObject's property-change signal
|
|
|
a85faa |
and searches for the D-Bus interface to which to send the
|
|
|
a85faa |
PropertiesChanged signal.
|
|
|
a85faa |
Then it would enqueue the value encoded as GVariant in pending_notifications.
|
|
|
a85faa |
However, thereby the association between the property that changed and the
|
|
|
a85faa |
interface was lost. So later in idle_emit_properties_changed() it would
|
|
|
a85faa |
just pick the first interface with a properties-changed-id.
|
|
|
a85faa |
|
|
|
a85faa |
That is wrong. pending_notifications must be associated with the D-Bus
|
|
|
a85faa |
interface that we are going to notify. That is, each InterfaceData must
|
|
|
a85faa |
have its own separate list.
|
|
|
a85faa |
|
|
|
a85faa |
This is broken since introducing NMExportedObject and moving to gdbus.
|
|
|
a85faa |
Only now it was discovered as NMDevice itself has two D-Bus interfaces:
|
|
|
a85faa |
"Device" and "Device.Statistics".
|
|
|
a85faa |
|
|
|
a85faa |
Note that the order of the PropertiesChanged in our D-Bus API is not defined
|
|
|
a85faa |
so that later signals can reach the receiver before earlier signals.
|
|
|
a85faa |
Also, multiple change signals for one property may be combined.
|
|
|
a85faa |
That is not changed by this patch and is not considered a bug, but something
|
|
|
a85faa |
that our D-Bus API wrt. PropertiesChanged does not guarantee.
|
|
|
a85faa |
|
|
|
a85faa |
https://bugzilla.gnome.org/show_bug.cgi?id=770629
|
|
|
a85faa |
(cherry picked from commit 82e94390deb86eab25290e83ca0cd0e5a703fd73)
|
|
|
a85faa |
(cherry picked from commit 8d9ea18b3d4a3c76fea7a9f07cd02772cc906732)
|
|
|
a85faa |
---
|
|
|
a85faa |
src/nm-exported-object.c | 104 ++++++++++++++++++++++++-----------------------
|
|
|
a85faa |
1 file changed, 53 insertions(+), 51 deletions(-)
|
|
|
a85faa |
|
|
|
a85faa |
diff --git a/src/nm-exported-object.c b/src/nm-exported-object.c
|
|
|
a85faa |
index c4dbab8..31ca3f2 100644
|
|
|
a85faa |
--- a/src/nm-exported-object.c
|
|
|
a85faa |
+++ b/src/nm-exported-object.c
|
|
|
a85faa |
@@ -38,14 +38,13 @@ G_DEFINE_ABSTRACT_TYPE (NMExportedObject, nm_exported_object, G_TYPE_DBUS_OBJECT
|
|
|
a85faa |
typedef struct {
|
|
|
a85faa |
GDBusInterfaceSkeleton *interface;
|
|
|
a85faa |
guint property_changed_signal_id;
|
|
|
a85faa |
+ GHashTable *pending_notifies;
|
|
|
a85faa |
} InterfaceData;
|
|
|
a85faa |
|
|
|
a85faa |
typedef struct {
|
|
|
a85faa |
NMBusManager *bus_mgr;
|
|
|
a85faa |
char *path;
|
|
|
a85faa |
|
|
|
a85faa |
- GHashTable *pending_notifies;
|
|
|
a85faa |
-
|
|
|
a85faa |
InterfaceData *interfaces;
|
|
|
a85faa |
guint num_interfaces;
|
|
|
a85faa |
|
|
|
a85faa |
@@ -268,8 +267,8 @@ nm_exported_object_class_add_interface (NMExportedObjectClass *object_class,
|
|
|
a85faa |
nm_exported_object_class_info_quark (), classinfo);
|
|
|
a85faa |
}
|
|
|
a85faa |
|
|
|
a85faa |
- classinfo->skeleton_types = g_slist_prepend (classinfo->skeleton_types,
|
|
|
a85faa |
- GSIZE_TO_POINTER (dbus_skeleton_type));
|
|
|
a85faa |
+ classinfo->skeleton_types = g_slist_append (classinfo->skeleton_types,
|
|
|
a85faa |
+ GSIZE_TO_POINTER (dbus_skeleton_type));
|
|
|
a85faa |
|
|
|
a85faa |
/* Ensure @dbus_skeleton_type's class_init has run, so its signals/properties
|
|
|
a85faa |
* will be defined.
|
|
|
a85faa |
@@ -492,6 +491,11 @@ nm_exported_object_create_skeletons (NMExportedObject *self,
|
|
|
a85faa |
g_dbus_object_skeleton_add_interface ((GDBusObjectSkeleton *) self, ifdata->interface);
|
|
|
a85faa |
|
|
|
a85faa |
ifdata->property_changed_signal_id = g_signal_lookup ("properties-changed", G_OBJECT_TYPE (ifdata->interface));
|
|
|
a85faa |
+
|
|
|
a85faa |
+ ifdata->pending_notifies = g_hash_table_new_full (g_direct_hash,
|
|
|
a85faa |
+ g_direct_equal,
|
|
|
a85faa |
+ NULL,
|
|
|
a85faa |
+ (GDestroyNotify) g_variant_unref);
|
|
|
a85faa |
}
|
|
|
a85faa |
nm_assert (i == 0);
|
|
|
a85faa |
|
|
|
a85faa |
@@ -542,6 +546,7 @@ nm_exported_object_destroy_skeletons (NMExportedObject *self)
|
|
|
a85faa |
|
|
|
a85faa |
g_dbus_object_skeleton_remove_interface ((GDBusObjectSkeleton *) self, ifdata->interface);
|
|
|
a85faa |
nm_exported_object_skeleton_release (ifdata->interface);
|
|
|
a85faa |
+ g_hash_table_destroy (ifdata->pending_notifies);
|
|
|
a85faa |
}
|
|
|
a85faa |
|
|
|
a85faa |
g_slice_free1 (sizeof (InterfaceData) * n, priv->interfaces);
|
|
|
a85faa |
@@ -701,11 +706,7 @@ nm_exported_object_unexport (NMExportedObject *self)
|
|
|
a85faa |
|
|
|
a85faa |
g_clear_pointer (&priv->path, g_free);
|
|
|
a85faa |
|
|
|
a85faa |
- if (nm_clear_g_source (&priv->notify_idle_id)) {
|
|
|
a85faa |
- /* We had a notification queued. Since we removed all interfaces,
|
|
|
a85faa |
- * the notification is obsolete and must be cleaned up. */
|
|
|
a85faa |
- g_hash_table_remove_all (priv->pending_notifies);
|
|
|
a85faa |
- }
|
|
|
a85faa |
+ nm_clear_g_source (&priv->notify_idle_id);
|
|
|
a85faa |
}
|
|
|
a85faa |
|
|
|
a85faa |
/*****************************************************************************/
|
|
|
a85faa |
@@ -784,53 +785,60 @@ static gboolean
|
|
|
a85faa |
idle_emit_properties_changed (gpointer self)
|
|
|
a85faa |
{
|
|
|
a85faa |
NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
|
|
|
a85faa |
- gs_unref_variant GVariant *variant = NULL;
|
|
|
a85faa |
- InterfaceData *ifdata = NULL;
|
|
|
a85faa |
- GHashTableIter hash_iter;
|
|
|
a85faa |
- GVariantBuilder notifies;
|
|
|
a85faa |
- guint i, n;
|
|
|
a85faa |
- PendingNotifiesItem *values;
|
|
|
a85faa |
+ guint k;
|
|
|
a85faa |
|
|
|
a85faa |
priv->notify_idle_id = 0;
|
|
|
a85faa |
|
|
|
a85faa |
+ for (k = 0; k < priv->num_interfaces; k++) {
|
|
|
a85faa |
+ InterfaceData *ifdata = &priv->interfaces[k];
|
|
|
a85faa |
+ gs_unref_variant GVariant *variant = NULL;
|
|
|
a85faa |
+ PendingNotifiesItem *values;
|
|
|
a85faa |
+ GVariantBuilder notifies;
|
|
|
a85faa |
+ GHashTableIter hash_iter;
|
|
|
a85faa |
+ guint i, n;
|
|
|
a85faa |
+
|
|
|
a85faa |
+ n = g_hash_table_size (ifdata->pending_notifies);
|
|
|
a85faa |
+ if (n == 0)
|
|
|
a85faa |
+ continue;
|
|
|
a85faa |
|
|
|
a85faa |
- n = g_hash_table_size (priv->pending_notifies);
|
|
|
a85faa |
- g_return_val_if_fail (n > 0, FALSE);
|
|
|
a85faa |
+ if (!ifdata->property_changed_signal_id)
|
|
|
a85faa |
+ goto next;
|
|
|
a85faa |
|
|
|
a85faa |
- values = g_alloca (sizeof (values[0]) * n);
|
|
|
a85faa |
+ /* We use here alloca in a loop, something that is usually avoided.
|
|
|
a85faa |
+ * But the number of interfaces "priv->num_interfaces" is small (determined by
|
|
|
a85faa |
+ * the depth of the type inheritence) and the number of possible pending_notifies
|
|
|
a85faa |
+ * "n" is small (determined by the number of GObject properties). */
|
|
|
a85faa |
+ values = g_alloca (sizeof (values[0]) * n);
|
|
|
a85faa |
|
|
|
a85faa |
- i = 0;
|
|
|
a85faa |
- g_hash_table_iter_init (&hash_iter, priv->pending_notifies);
|
|
|
a85faa |
- while (g_hash_table_iter_next (&hash_iter, (gpointer) &values[i].property_name, (gpointer) &values[i].variant))
|
|
|
a85faa |
- i++;
|
|
|
a85faa |
- nm_assert (i == n);
|
|
|
a85faa |
+ i = 0;
|
|
|
a85faa |
+ g_hash_table_iter_init (&hash_iter, ifdata->pending_notifies);
|
|
|
a85faa |
+ while (g_hash_table_iter_next (&hash_iter, (gpointer) &values[i].property_name, (gpointer) &values[i].variant))
|
|
|
a85faa |
+ i++;
|
|
|
a85faa |
+ nm_assert (i == n);
|
|
|
a85faa |
|
|
|
a85faa |
- g_qsort_with_data (values, n, sizeof (values[0]), _sort_pending_notifies, NULL);
|
|
|
a85faa |
+ g_qsort_with_data (values, n, sizeof (values[0]), _sort_pending_notifies, NULL);
|
|
|
a85faa |
|
|
|
a85faa |
- g_variant_builder_init (¬ifies, G_VARIANT_TYPE_VARDICT);
|
|
|
a85faa |
- for (i = 0; i < n; i++)
|
|
|
a85faa |
- g_variant_builder_add (¬ifies, "{sv}", values[i].property_name, values[i].variant);
|
|
|
a85faa |
- variant = g_variant_ref_sink (g_variant_builder_end (¬ifies));
|
|
|
a85faa |
+ g_variant_builder_init (¬ifies, G_VARIANT_TYPE_VARDICT);
|
|
|
a85faa |
+ for (i = 0; i < n; i++)
|
|
|
a85faa |
+ g_variant_builder_add (¬ifies, "{sv}", values[i].property_name, values[i].variant);
|
|
|
a85faa |
+ variant = g_variant_ref_sink (g_variant_builder_end (¬ifies));
|
|
|
a85faa |
|
|
|
a85faa |
- g_hash_table_remove_all (priv->pending_notifies);
|
|
|
a85faa |
|
|
|
a85faa |
- for (i = 0; i < priv->num_interfaces; i++) {
|
|
|
a85faa |
- if (priv->interfaces[i].property_changed_signal_id != 0) {
|
|
|
a85faa |
- ifdata = &priv->interfaces[i];
|
|
|
a85faa |
- break;
|
|
|
a85faa |
+ if (nm_logging_enabled (LOGL_DEBUG, LOGD_DBUS_PROPS)) {
|
|
|
a85faa |
+ gs_free char *notification = g_variant_print (variant, TRUE);
|
|
|
a85faa |
+
|
|
|
a85faa |
+ nm_log_dbg (LOGD_DBUS_PROPS, "PropertiesChanged %s, %s, %p: %s",
|
|
|
a85faa |
+ G_OBJECT_TYPE_NAME (self), G_OBJECT_TYPE_NAME (ifdata->interface),
|
|
|
a85faa |
+ self, notification);
|
|
|
a85faa |
}
|
|
|
a85faa |
- }
|
|
|
a85faa |
- g_return_val_if_fail (ifdata, FALSE);
|
|
|
a85faa |
|
|
|
a85faa |
- if (nm_logging_enabled (LOGL_DEBUG, LOGD_DBUS_PROPS)) {
|
|
|
a85faa |
- gs_free char *notification = g_variant_print (variant, TRUE);
|
|
|
a85faa |
+ g_signal_emit (ifdata->interface, ifdata->property_changed_signal_id, 0, variant);
|
|
|
a85faa |
|
|
|
a85faa |
- nm_log_dbg (LOGD_DBUS_PROPS, "PropertiesChanged %s %p: %s",
|
|
|
a85faa |
- G_OBJECT_TYPE_NAME (self), self, notification);
|
|
|
a85faa |
+next:
|
|
|
a85faa |
+ g_hash_table_remove_all (ifdata->pending_notifies);
|
|
|
a85faa |
}
|
|
|
a85faa |
|
|
|
a85faa |
- g_signal_emit (ifdata->interface, ifdata->property_changed_signal_id, 0, variant);
|
|
|
a85faa |
- return FALSE;
|
|
|
a85faa |
+ return G_SOURCE_REMOVE;
|
|
|
a85faa |
}
|
|
|
a85faa |
|
|
|
a85faa |
static void
|
|
|
a85faa |
@@ -841,6 +849,7 @@ nm_exported_object_notify (GObject *object, GParamSpec *pspec)
|
|
|
a85faa |
GType type;
|
|
|
a85faa |
const char *dbus_property_name = NULL;
|
|
|
a85faa |
GValue value = G_VALUE_INIT;
|
|
|
a85faa |
+ InterfaceData *ifdata = NULL;
|
|
|
a85faa |
const GVariantType *vtype;
|
|
|
a85faa |
guint i, j;
|
|
|
a85faa |
|
|
|
a85faa |
@@ -863,10 +872,10 @@ nm_exported_object_notify (GObject *object, GParamSpec *pspec)
|
|
|
a85faa |
}
|
|
|
a85faa |
|
|
|
a85faa |
for (i = 0; i < priv->num_interfaces; i++) {
|
|
|
a85faa |
- GDBusInterfaceSkeleton *skel = priv->interfaces[i].interface;
|
|
|
a85faa |
GDBusInterfaceInfo *iinfo;
|
|
|
a85faa |
|
|
|
a85faa |
- iinfo = g_dbus_interface_skeleton_get_info (skel);
|
|
|
a85faa |
+ ifdata = &priv->interfaces[i];
|
|
|
a85faa |
+ iinfo = g_dbus_interface_skeleton_get_info (ifdata->interface);
|
|
|
a85faa |
for (j = 0; iinfo->properties[j]; j++) {
|
|
|
a85faa |
if (nm_streq (iinfo->properties[j]->name, dbus_property_name)) {
|
|
|
a85faa |
vtype = G_VARIANT_TYPE (iinfo->properties[j]->signature);
|
|
|
a85faa |
@@ -882,7 +891,7 @@ vtype_found:
|
|
|
a85faa |
|
|
|
a85faa |
/* @dbus_property_name is inside classinfo and never freed, thus we don't clone it.
|
|
|
a85faa |
* Also, we do a pointer, not string comparison. */
|
|
|
a85faa |
- g_hash_table_insert (priv->pending_notifies,
|
|
|
a85faa |
+ g_hash_table_insert (ifdata->pending_notifies,
|
|
|
a85faa |
(gpointer) dbus_property_name,
|
|
|
a85faa |
g_dbus_gvalue_to_gvariant (&value, vtype));
|
|
|
a85faa |
g_value_unset (&value);
|
|
|
a85faa |
@@ -896,12 +905,6 @@ vtype_found:
|
|
|
a85faa |
static void
|
|
|
a85faa |
nm_exported_object_init (NMExportedObject *self)
|
|
|
a85faa |
{
|
|
|
a85faa |
- NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
|
|
|
a85faa |
-
|
|
|
a85faa |
- priv->pending_notifies = g_hash_table_new_full (g_direct_hash,
|
|
|
a85faa |
- g_direct_equal,
|
|
|
a85faa |
- NULL,
|
|
|
a85faa |
- (GDestroyNotify) g_variant_unref);
|
|
|
a85faa |
}
|
|
|
a85faa |
|
|
|
a85faa |
static void
|
|
|
a85faa |
@@ -937,7 +940,6 @@ nm_exported_object_dispose (GObject *object)
|
|
|
a85faa |
} else
|
|
|
a85faa |
g_clear_pointer (&priv->path, g_free);
|
|
|
a85faa |
|
|
|
a85faa |
- g_clear_pointer (&priv->pending_notifies, g_hash_table_destroy);
|
|
|
a85faa |
nm_clear_g_source (&priv->notify_idle_id);
|
|
|
a85faa |
|
|
|
a85faa |
G_OBJECT_CLASS (nm_exported_object_parent_class)->dispose (object);
|
|
|
a85faa |
--
|
|
|
a85faa |
2.7.4
|
|
|
a85faa |
|
|
|
a85faa |
|
|
|
a85faa |
From a7c15ef9713a25c34c244f3684df564da09af093 Mon Sep 17 00:00:00 2001
|
|
|
a85faa |
From: Thomas Haller <thaller@redhat.com>
|
|
|
a85faa |
Date: Wed, 31 Aug 2016 11:33:01 +0200
|
|
|
a85faa |
Subject: [PATCH 2/2] exported-object: cleanup logging about properties-changed
|
|
|
a85faa |
|
|
|
a85faa |
(cherry picked from commit 46f285e3d38d64af647495d0d83efa2f9a8ea1aa)
|
|
|
a85faa |
(cherry picked from commit 4f452eedab24f9c9a0d282691ae2e600c6b6c310)
|
|
|
a85faa |
---
|
|
|
a85faa |
src/nm-exported-object.c | 10 +++++-----
|
|
|
a85faa |
1 file changed, 5 insertions(+), 5 deletions(-)
|
|
|
a85faa |
|
|
|
a85faa |
diff --git a/src/nm-exported-object.c b/src/nm-exported-object.c
|
|
|
a85faa |
index 31ca3f2..d99a9ce 100644
|
|
|
a85faa |
--- a/src/nm-exported-object.c
|
|
|
a85faa |
+++ b/src/nm-exported-object.c
|
|
|
a85faa |
@@ -827,9 +827,9 @@ idle_emit_properties_changed (gpointer self)
|
|
|
a85faa |
if (nm_logging_enabled (LOGL_DEBUG, LOGD_DBUS_PROPS)) {
|
|
|
a85faa |
gs_free char *notification = g_variant_print (variant, TRUE);
|
|
|
a85faa |
|
|
|
a85faa |
- nm_log_dbg (LOGD_DBUS_PROPS, "PropertiesChanged %s, %s, %p: %s",
|
|
|
a85faa |
- G_OBJECT_TYPE_NAME (self), G_OBJECT_TYPE_NAME (ifdata->interface),
|
|
|
a85faa |
- self, notification);
|
|
|
a85faa |
+ nm_log_dbg (LOGD_DBUS_PROPS, "properties-changed[%p]: type %s, iface %s: %s",
|
|
|
a85faa |
+ self, G_OBJECT_TYPE_NAME (self), G_OBJECT_TYPE_NAME (ifdata->interface),
|
|
|
a85faa |
+ notification);
|
|
|
a85faa |
}
|
|
|
a85faa |
|
|
|
a85faa |
g_signal_emit (ifdata->interface, ifdata->property_changed_signal_id, 0, variant);
|
|
|
a85faa |
@@ -866,8 +866,8 @@ nm_exported_object_notify (GObject *object, GParamSpec *pspec)
|
|
|
a85faa |
break;
|
|
|
a85faa |
}
|
|
|
a85faa |
if (!dbus_property_name) {
|
|
|
a85faa |
- nm_log_trace (LOGD_DBUS_PROPS, "ignoring notification for prop %s on type %s",
|
|
|
a85faa |
- pspec->name, G_OBJECT_TYPE_NAME (object));
|
|
|
a85faa |
+ nm_log_trace (LOGD_DBUS_PROPS, "properties-changed[%p]: ignoring notification for prop %s on type %s",
|
|
|
a85faa |
+ object, pspec->name, G_OBJECT_TYPE_NAME (object));
|
|
|
a85faa |
return;
|
|
|
a85faa |
}
|
|
|
a85faa |
|
|
|
a85faa |
--
|
|
|
a85faa |
2.7.4
|
|
|
a85faa |
|