summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-01-31 00:54:46 +0100
committerThomas Haller <thaller@redhat.com>2020-02-10 12:17:34 +0100
commit1f9f077657fcb72f2e72f2cee1de9c81f82d4b41 (patch)
tree7ba9a87e69c7ffc2e237a7f323f4439a8c08428d
parentf1b8d7d179e8af36b413bfca5b0c588a3a6b4db4 (diff)
downloadNetworkManager-th/libnm-active-connection-delay-ready.tar.gz
libnm: hide NMActiveConnection until NMRemoteConnection is readyth/libnm-active-connection-delay-ready
Generally, libnm's NMClient cache only wants to expose NMObjects that are fully initalized. Most objects don't require anything special, except NMRemoteConnection which waits for the GetSettings() call to complete. NMObjects reference each other. For example, NMActiveConnection references NMDevice and NMRemoteConnection. There is a desire that an object is only ready, if the objects that it references are ready too. In practice that is not done, because usually every objects references other objects, that means all objects would be declared as non-ready as long as any of them is still initializing. That does not seem desirable. Instead, most objects (except NMRemoteConnection and now NMActiveConnection) are considered ready and visible, once their first notification completes. In case the objects reference any object that is not yet ready, the references is NULL (but the source object is visible already). This is also done this way, to cope with cycles where objects reference each other. In practice, such cycles should not be exposed by NetworkManager. However, libnm should be robust against that. This has the undesired effect that when you call AddAndActivate(), then the NMActiveConnection might already be visible while its NMRemoteConnection isn't. That means, ac.get_connection() will initially return NULL, until the remote connection becomes ready. Also add a special handling that NMActiveConnection waits for their NMRemoteConnection to be ready, before being ready itself. Fixes: ce0e898fb476 ('libnm: refactor caching of D-Bus objects in NMClient')
-rw-r--r--libnm/nm-active-connection.c29
-rw-r--r--libnm/nm-client.c8
-rw-r--r--libnm/nm-libnm-utils.h2
3 files changed, 39 insertions, 0 deletions
diff --git a/libnm/nm-active-connection.c b/libnm/nm-active-connection.c
index aa8504e61d..ade2edbe73 100644
--- a/libnm/nm-active-connection.c
+++ b/libnm/nm-active-connection.c
@@ -425,6 +425,33 @@ _nm_active_connection_state_changed_commit (NMActiveConnection *self,
_notify_event_state_changed,
g_object_ref (self));
}
+/*****************************************************************************/
+
+static gboolean
+is_ready (NMObject *nmobj)
+{
+ NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (nmobj);
+
+ /* Usually, we don't want to expose our NMObject instances until they are fully initialized.
+ * For NMRemoteSetting this means to wait until GetSettings() returns.
+ *
+ * Note that most object types reference each other (directly or indirectly). E.g. the
+ * NMActiveConnection refers to the NMRemoteConnection and the NMDevice instance. So,
+ * we don't want to hide them too long, otherwise basically the entire set of objects
+ * will be hidden until they are all initialized. So, usually, when a NMObject references
+ * objects that are not yet initialized, that reference will just be NULL but the object
+ * will be considered ready already.
+ *
+ * For NMActiveConnection referencing a NMRemoteConnection don't do that. Here we wait for the
+ * NMRemoteConnection to be ready as well. This is somewhat arbitrary special casing, but
+ * the effect is that when nm_client_add_and_activate*() returns, the NMActiveConnection already
+ * references a initialized NMRemoteConnection.
+ */
+ if (!nml_dbus_property_o_is_ready_fully (&priv->property_o[PROPERTY_O_IDX_CONNECTION]))
+ return FALSE;
+
+ return NM_OBJECT_CLASS (nm_active_connection_parent_class)->is_ready (nmobj);
+}
/*****************************************************************************/
@@ -550,6 +577,8 @@ nm_active_connection_class_init (NMActiveConnectionClass *klass)
object_class->get_property = get_property;
object_class->finalize = finalize;
+ nm_object_class->is_ready = is_ready;
+
_NM_OBJECT_CLASS_INIT_PRIV_PTR_INDIRECT (nm_object_class, NMActiveConnection);
_NM_OBJECT_CLASS_INIT_PROPERTY_O_FIELDS_N (nm_object_class, NMActiveConnectionPrivate, property_o);
diff --git a/libnm/nm-client.c b/libnm/nm-client.c
index 154ad1c992..a93a81c353 100644
--- a/libnm/nm-client.c
+++ b/libnm/nm-client.c
@@ -1594,6 +1594,14 @@ nml_dbus_property_o_is_ready (const NMLDBusPropertyO *pr_o)
|| !pr_o->owner_dbobj;
}
+gboolean
+nml_dbus_property_o_is_ready_fully (const NMLDBusPropertyO *pr_o)
+{
+ return !pr_o->owner_dbobj
+ || !pr_o->obj_watcher
+ || pr_o->nmobj;
+}
+
static void
nml_dbus_property_o_notify_changed (NMLDBusPropertyO *pr_o,
NMClient *self)
diff --git a/libnm/nm-libnm-utils.h b/libnm/nm-libnm-utils.h
index f2affc5f62..28c9c1164c 100644
--- a/libnm/nm-libnm-utils.h
+++ b/libnm/nm-libnm-utils.h
@@ -260,6 +260,8 @@ gpointer nml_dbus_property_o_get_obj (NMLDBusPropertyO *pr_o);
gboolean nml_dbus_property_o_is_ready (const NMLDBusPropertyO *pr_o);
+gboolean nml_dbus_property_o_is_ready_fully (const NMLDBusPropertyO *pr_o);
+
void nml_dbus_property_o_clear (NMLDBusPropertyO *pr_o,
NMClient *client);