Blame SOURCES/0005-dbus-prop-changed-signal-source-rh1371920.patch

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 (&notifies, G_VARIANT_TYPE_VARDICT);
a85faa
-	for (i = 0; i < n; i++)
a85faa
-		g_variant_builder_add (&notifies, "{sv}", values[i].property_name, values[i].variant);
a85faa
-	variant = g_variant_ref_sink (g_variant_builder_end (&notifies));
a85faa
+		g_variant_builder_init (&notifies, G_VARIANT_TYPE_VARDICT);
a85faa
+		for (i = 0; i < n; i++)
a85faa
+			g_variant_builder_add (&notifies, "{sv}", values[i].property_name, values[i].variant);
a85faa
+		variant = g_variant_ref_sink (g_variant_builder_end (&notifies));
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