about summary refs log tree commit diff
path: root/libnm
diff options
context:
space:
mode:
Diffstat (limited to 'libnm')
-rw-r--r--libnm/nm-device-vlan.c7
-rw-r--r--libnm/nm-device-vxlan.c2
-rw-r--r--libnm/nm-manager.c22
-rw-r--r--libnm/nm-object.c217
-rw-r--r--libnm/nm-secret-agent-old.c1
-rw-r--r--libnm/nm-vpn-service-plugin.c1
-rw-r--r--libnm/tests/test-nm-client.c2
7 files changed, 143 insertions, 109 deletions
diff --git a/libnm/nm-device-vlan.c b/libnm/nm-device-vlan.c
index 843dda02..330d6f4a 100644
--- a/libnm/nm-device-vlan.c
+++ b/libnm/nm-device-vlan.c
@@ -116,6 +116,7 @@ nm_device_vlan_get_vlan_id (NMDeviceVlan *device)
 static gboolean
 connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
 {
+	NMDeviceVlanPrivate *priv;
 	NMSettingVlan *s_vlan;
 	NMSettingWired *s_wired;
 	const char *setting_hwaddr;
@@ -142,8 +143,10 @@ connection_compatible (NMDevice *device, NMConnection *connection, GError **erro
 	else
 		setting_hwaddr = NULL;
 	if (setting_hwaddr) {
-		if (!nm_utils_hwaddr_matches (setting_hwaddr, -1,
-		                              NM_DEVICE_VLAN_GET_PRIVATE (device)->hw_address, -1)) {
+		priv = NM_DEVICE_VLAN_GET_PRIVATE (device);
+		if (   !priv->hw_address
+		    || !nm_utils_hwaddr_matches (setting_hwaddr, -1,
+		                                 priv->hw_address, -1)) {
 			g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
 			                     _("The hardware address of the device and the connection didn't match."));
 		}
diff --git a/libnm/nm-device-vxlan.c b/libnm/nm-device-vxlan.c
index 335498ee..c8da6c64 100644
--- a/libnm/nm-device-vxlan.c
+++ b/libnm/nm-device-vxlan.c
@@ -458,6 +458,8 @@ finalize (GObject *object)
 
 	g_free (priv->hw_address);
 	g_clear_object (&priv->parent);
+	g_free (priv->group);
+	g_free (priv->local);
 
 	G_OBJECT_CLASS (nm_device_vxlan_parent_class)->finalize (object);
 }
diff --git a/libnm/nm-manager.c b/libnm/nm-manager.c
index c3d0c51d..dc14f83d 100644
--- a/libnm/nm-manager.c
+++ b/libnm/nm-manager.c
@@ -1201,12 +1201,11 @@ free_devices (NMManager *manager, gboolean in_dispose)
 	if (in_dispose) {
 		priv->devices = NULL;
 		priv->all_devices = NULL;
-		return;
+	} else {
+		priv->devices = g_ptr_array_new_with_free_func (g_object_unref);
+		priv->all_devices = g_ptr_array_new_with_free_func (g_object_unref);
 	}
 
-	priv->devices = g_ptr_array_new_with_free_func (g_object_unref);
-	priv->all_devices = g_ptr_array_new_with_free_func (g_object_unref);
-
 	if (all_devices && all_devices->len > 0)
 		devices = all_devices;
 	else if (real_devices && real_devices->len > 0)
@@ -1222,14 +1221,23 @@ free_devices (NMManager *manager, gboolean in_dispose)
 						goto next;
 				}
 			}
-			g_signal_emit (manager, signals[DEVICE_REMOVED], 0, d);
+			if (in_dispose)
+				device_removed (manager, d);
+			else
+				g_signal_emit (manager, signals[DEVICE_REMOVED], 0, d);
 next:
 			;
 		}
 	}
 	if (devices) {
-		for (i = 0; i < devices->len; i++)
-			g_signal_emit (manager, signals[DEVICE_REMOVED], 0, devices->pdata[i]);
+		for (i = 0; i < devices->len; i++) {
+			NMDevice *d = devices->pdata[i];
+
+			if (in_dispose)
+				device_removed (manager, d);
+			else
+				g_signal_emit (manager, signals[DEVICE_REMOVED], 0, d);
+		}
 	}
 }
 
diff --git a/libnm/nm-object.c b/libnm/nm-object.c
index 3b41041e..20395ce8 100644
--- a/libnm/nm-object.c
+++ b/libnm/nm-object.c
@@ -95,6 +95,8 @@ typedef struct {
 	GSList *reload_results;
 	guint reload_remaining;
 	GError *reload_error;
+
+	GSList *pending;        /* ordered list of pending property updates. */
 } NMObjectPrivate;
 
 enum {
@@ -447,7 +449,7 @@ typedef struct {
 	GObject **objects;
 	int length, remaining;
 
-	GPtrArray *array;
+	gboolean array;
 	const char *property_name;
 } ObjectCreatedData;
 
@@ -458,12 +460,10 @@ odata_free (gpointer data)
 
 	g_object_unref (odata->self);
 	g_free (odata->objects);
-	if (odata->array)
-		g_ptr_array_unref (odata->array);
 	g_slice_free (ObjectCreatedData, odata);
 }
 
-static void object_property_maybe_complete (ObjectCreatedData *odata);
+static void object_property_maybe_complete (NMObject *self);
 
 
 typedef void (*NMObjectCreateCallbackFunc) (GObject *, const char *, gpointer);
@@ -488,14 +488,29 @@ create_async_complete (GObject *object, NMObjectTypeAsyncData *async_data)
 static void
 create_async_inited (GObject *object, GAsyncResult *result, gpointer user_data)
 {
+	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+	NMObjectPrivate *odata_priv;
 	NMObjectTypeAsyncData *async_data = user_data;
 	GError *error = NULL;
+	ObjectCreatedData *odata;
 
-	NM_OBJECT_GET_PRIVATE (object)->inited = TRUE;
+	priv->inited = TRUE;
 	if (!g_async_initable_init_finish (G_ASYNC_INITABLE (object), result, &error)) {
 		dbgmsg ("Could not create object for %s: %s",
 		        nm_object_get_path (NM_OBJECT (object)),
 		        error->message);
+
+		while (priv->waiters) {
+			odata = priv->waiters->data;
+			odata_priv = NM_OBJECT_GET_PRIVATE (odata->self);
+
+			priv->waiters = g_slist_remove (priv->waiters, odata);
+			if (!odata_priv->reload_error)
+				odata_priv->reload_error = g_error_copy (error);
+			odata_priv->reload_remaining--;
+			reload_complete (odata->self, FALSE);
+		}
+
 		g_error_free (error);
 		g_clear_object (&object);
 	}
@@ -503,15 +518,12 @@ create_async_inited (GObject *object, GAsyncResult *result, gpointer user_data)
 	create_async_complete (object, async_data);
 
 	if (object) {
-		NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
-
 		/* There are some object properties whose creation couldn't proceed
 		 * because it depended on this object. */
 		while (priv->waiters) {
-			ObjectCreatedData *odata = priv->waiters->data;
-
+			odata = priv->waiters->data;
 			priv->waiters = g_slist_remove (priv->waiters, odata);
-			object_property_maybe_complete (odata);
+			object_property_maybe_complete (odata->self);
 		}
 	}
 }
@@ -716,104 +728,117 @@ already_awaits (ObjectCreatedData *odata, GObject *object)
 }
 
 static void
-object_property_maybe_complete (ObjectCreatedData *odata)
+object_property_maybe_complete (NMObject *self)
 {
-	NMObject *self = odata->self;
 	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
-	PropertyInfo *pi = odata->pi;
-	gboolean different = TRUE;
+	/* The odata may hold the last reference. */
+	_nm_unused gs_unref_object NMObject *self_keep_alive = g_object_ref (self);
 	int i;
 
-	/* Only complete the array property load when all the objects are initialized. */
-	for (i = 0; i < odata->length; i++) {
-		GObject *obj = odata->objects[i];
-		NMObjectPrivate *obj_priv;
-
-		/* Could not load the object. Perhaps it was removed. */
-		if (!obj)
-			continue;
+	while (priv->pending) {
+		ObjectCreatedData *odata = priv->pending->data;
+		PropertyInfo *pi = odata->pi;
+		gboolean different = TRUE;
 
-		obj_priv = NM_OBJECT_GET_PRIVATE (obj);
-		if (!obj_priv->inited) {
-
-			/* The object is not finished because we block its creation. */
-			if (already_awaits (odata, obj))
-				continue;
-
-			if (!g_slist_find (obj_priv->waiters, odata))
-				obj_priv->waiters = g_slist_prepend (obj_priv->waiters, odata);
+		if (odata->remaining > 0)
 			return;
-		}
-	}
-
-	if (odata->array) {
-		GPtrArray *pi_old = *((GPtrArray **) pi->field);
-		GPtrArray *old = odata->array;
-		GPtrArray *new;
-
-		/* Build up new array */
-		new = g_ptr_array_new_full (odata->length, g_object_unref);
-		for (i = 0; i < odata->length; i++)
-			add_to_object_array_unique (new, odata->objects[i]);
 
-		*((GPtrArray **) pi->field) = new;
+		/* Only complete the array property load when all the objects are initialized. */
+		for (i = 0; i < odata->length; i++) {
+			GObject *obj = odata->objects[i];
+			NMObjectPrivate *obj_priv;
 
-		if (pi->signal_prefix) {
-			GPtrArray *added = g_ptr_array_sized_new (3);
-			GPtrArray *removed = g_ptr_array_sized_new (3);
+			/* Could not load the object. Perhaps it was removed. */
+			if (!obj)
+				continue;
 
-			/* Find objects in 'old' that do not exist in 'new' */
-			array_diff (old, new, removed);
+			obj_priv = NM_OBJECT_GET_PRIVATE (obj);
+			if (!obj_priv->inited) {
 
-			/* Find objects in 'new' that do not exist in old */
-			array_diff (new, old, added);
+				/* The object is not finished because we block its creation. */
+				if (already_awaits (odata, obj))
+					continue;
 
-			/* Emit added & removed */
-			for (i = 0; i < removed->len; i++) {
-				queue_added_removed_signal (self,
-				                            pi->signal_prefix,
-				                            g_ptr_array_index (removed, i),
-				                            FALSE);
+				if (!g_slist_find (obj_priv->waiters, odata))
+					obj_priv->waiters = g_slist_prepend (obj_priv->waiters, odata);
+				return;
 			}
+		}
 
-			for (i = 0; i < added->len; i++) {
-				queue_added_removed_signal (self,
-				                            pi->signal_prefix,
-				                            g_ptr_array_index (added, i),
-				                            TRUE);
+		if (odata->array) {
+			GPtrArray *old = *((GPtrArray **) pi->field);
+			GPtrArray *new;
+
+			/* Build up new array */
+			new = g_ptr_array_new_full (odata->length, g_object_unref);
+			for (i = 0; i < odata->length; i++)
+				add_to_object_array_unique (new, odata->objects[i]);
+
+			*((GPtrArray **) pi->field) = new;
+
+			if (pi->signal_prefix) {
+				GPtrArray *added = g_ptr_array_sized_new (3);
+				GPtrArray *removed = g_ptr_array_sized_new (3);
+
+				if (old) {
+					/* Find objects in 'old' that do not exist in 'new' */
+					array_diff (old, new, removed);
+
+					/* Find objects in 'new' that do not exist in old */
+					array_diff (new, old, added);
+				} else {
+					for (i = 0; i < new->len; i++)
+						g_ptr_array_add (added, g_ptr_array_index (new, i));
+				}
+
+				/* Emit added & removed */
+				for (i = 0; i < removed->len; i++) {
+					queue_added_removed_signal (self,
+								    pi->signal_prefix,
+								    g_ptr_array_index (removed, i),
+								    FALSE);
+				}
+
+				for (i = 0; i < added->len; i++) {
+					queue_added_removed_signal (self,
+								    pi->signal_prefix,
+								    g_ptr_array_index (added, i),
+								    TRUE);
+				}
+
+				different = removed->len || added->len;
+				g_ptr_array_unref (added);
+				g_ptr_array_unref (removed);
+			} else {
+				/* No added/removed signals to send, just replace the property with
+				 * the new values.
+				 */
+				different = TRUE;
 			}
 
-			different = removed->len || added->len;
-			g_ptr_array_unref (added);
-			g_ptr_array_unref (removed);
-		} else {
-			/* No added/removed signals to send, just replace the property with
-			 * the new values.
+			/* Free old array last since it will release references, thus freeing
+			 * any objects in the 'removed' array.
 			 */
-			different = TRUE;
-		}
-
-		/* Free old array last since it will release references, thus freeing
-		 * any objects in the 'removed' array.
-		 */
-		if (pi_old)
-			g_ptr_array_unref (pi_old);
-	} else {
-		GObject **obj_p = pi->field;
+			if (old)
+				g_ptr_array_unref (old);
+		} else {
+			GObject **obj_p = pi->field;
 
-		different = (*obj_p != odata->objects[0]);
-		if (*obj_p)
-			g_object_unref (*obj_p);
-		*obj_p = odata->objects[0];
-	}
+			different = (*obj_p != odata->objects[0]);
+			if (*obj_p)
+				g_object_unref (*obj_p);
+			*obj_p = odata->objects[0];
+		}
 
-	if (different && odata->property_name)
-		_nm_object_queue_notify (self, odata->property_name);
+		if (different && odata->property_name)
+			_nm_object_queue_notify (self, odata->property_name);
 
-	if (--priv->reload_remaining == 0)
-		reload_complete (self, FALSE);
+		if (--priv->reload_remaining == 0)
+			reload_complete (self, TRUE);
 
-	odata_free (odata);
+		priv->pending = g_slist_remove (priv->pending, odata);
+		odata_free (odata);
+	}
 }
 
 static void
@@ -831,8 +856,7 @@ object_created (GObject *obj, const char *path, gpointer user_data)
 	}
 
 	odata->objects[--odata->remaining] = obj;
-	if (!odata->remaining)
-		object_property_maybe_complete (odata);
+	object_property_maybe_complete (odata->self);
 }
 
 static gboolean
@@ -849,9 +873,10 @@ handle_object_property (NMObject *self, const char *property_name, GVariant *val
 	odata->pi = pi;
 	odata->objects = g_new (GObject *, 1);
 	odata->length = odata->remaining = 1;
-	odata->array = NULL;
+	odata->array = FALSE;
 	odata->property_name = property_name;
 
+	priv->pending = g_slist_append (priv->pending, odata);
 	priv->reload_remaining++;
 
 	path = g_variant_get_string (value, NULL);
@@ -888,7 +913,6 @@ handle_object_array_property (NMObject *self, const char *property_name, GVarian
 	GPtrArray **array = pi->field;
 	const char *path;
 	ObjectCreatedData *odata;
-	guint i, len = *array ? (*array)->len : 0;
 
 	npaths = g_variant_n_children (value);
 
@@ -897,17 +921,14 @@ handle_object_array_property (NMObject *self, const char *property_name, GVarian
 	odata->pi = pi;
 	odata->objects = g_new0 (GObject *, npaths);
 	odata->length = odata->remaining = npaths;
+	odata->array = TRUE;
 	odata->property_name = property_name;
 
-	/* Objects known at this point. */
-	odata->array = g_ptr_array_new_full (len, g_object_unref);
-	for (i = 0; i < len; i++)
-		g_ptr_array_add (odata->array, g_object_ref (g_ptr_array_index (*array, i)));
-
+	priv->pending = g_slist_append (priv->pending, odata);
 	priv->reload_remaining++;
 
 	if (npaths == 0) {
-		object_property_maybe_complete (odata);
+		object_property_maybe_complete (self);
 		return TRUE;
 	}
 
diff --git a/libnm/nm-secret-agent-old.c b/libnm/nm-secret-agent-old.c
index 02a3f685..5f9ca216 100644
--- a/libnm/nm-secret-agent-old.c
+++ b/libnm/nm-secret-agent-old.c
@@ -613,7 +613,6 @@ reg_request_cb (GObject *proxy,
 	if (!nmdbus_agent_manager_call_register_finish (NMDBUS_AGENT_MANAGER (proxy), result, &error))
 		g_dbus_error_strip_remote_error (error);
 	reg_result (self, simple, error);
-	g_clear_error (&error);
 }
 
 static void
diff --git a/libnm/nm-vpn-service-plugin.c b/libnm/nm-vpn-service-plugin.c
index 64316296..8272943d 100644
--- a/libnm/nm-vpn-service-plugin.c
+++ b/libnm/nm-vpn-service-plugin.c
@@ -225,6 +225,7 @@ nm_vpn_service_plugin_disconnect (NMVpnServicePlugin *plugin, GError **err)
 		break;
 	case NM_VPN_SERVICE_STATE_INIT:
 		ret = TRUE;
+		nm_vpn_service_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPED);
 		break;
 
 	default:
diff --git a/libnm/tests/test-nm-client.c b/libnm/tests/test-nm-client.c
index 3a7c4d5d..bc219aa3 100644
--- a/libnm/tests/test-nm-client.c
+++ b/libnm/tests/test-nm-client.c
@@ -1346,7 +1346,7 @@ test_connection_invalid (void)
 	                               &path3);
 
 
-	nmtst_main_loop_run (loop, 100);
+	nmtst_main_loop_run (loop, 1000);
 
 
 	connections = nm_client_get_connections (client);