diff options
| author | Michael Biebl <biebl@debian.org> | 2020-01-31 12:10:14 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2020-01-31 12:10:14 +0100 |
| commit | f3c6d0765dff885e168b94f28e06ecc640315a74 (patch) | |
| tree | 30d67309f4d9b48ad269dfad6e80e5c15373ea75 /libnm/nm-client.c | |
| parent | 90c93214efba0966274224a93a77d235d4f8c034 (diff) | |
New upstream version 1.22.6 upstream/1.22.6
Diffstat (limited to 'libnm/nm-client.c')
| -rw-r--r-- | libnm/nm-client.c | 117 |
1 files changed, 102 insertions, 15 deletions
diff --git a/libnm/nm-client.c b/libnm/nm-client.c index eabbe022..4fa1c1f3 100644 --- a/libnm/nm-client.c +++ b/libnm/nm-client.c @@ -2988,9 +2988,12 @@ _dbus_handle_interface_removed (NMClient *self, } static void -_dbus_managed_objects_changed_cb (const char *object_path, - GVariant *added_interfaces_and_properties, - const char *const*removed_interfaces, +_dbus_managed_objects_changed_cb (GDBusConnection *connection, + const char *sender_name, + const char *arg_object_path, + const char *interface_name, + const char *signal_name, + GVariant *parameters, gpointer user_data) { NMClient *self = user_data; @@ -2998,19 +3001,50 @@ _dbus_managed_objects_changed_cb (const char *object_path, const char *log_context; gboolean changed; + nm_assert (nm_streq0 (interface_name, DBUS_INTERFACE_OBJECT_MANAGER)); + if (priv->get_managed_objects_cancellable) { /* we still wait for the initial GetManagedObjects(). Ignore the event. */ return; } - if (!added_interfaces_and_properties) { - log_context = "interfaces-removed"; - changed = _dbus_handle_interface_removed (self, log_context, object_path, NULL, removed_interfaces); - } else { + if (nm_streq (signal_name, "InterfacesAdded")) { + gs_unref_variant GVariant *interfaces_and_properties = NULL; + const char *object_path; + + if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(oa{sa{sv}})"))) + return; + + g_variant_get (parameters, + "(&o@a{sa{sv}})", + &object_path, + &interfaces_and_properties); + log_context = "interfaces-added"; - changed = _dbus_handle_interface_added (self, log_context, object_path, added_interfaces_and_properties); + changed = _dbus_handle_interface_added (self, log_context, object_path, interfaces_and_properties); + goto out; + } + + if (nm_streq (signal_name, "InterfacesRemoved")) { + gs_free const char **interfaces = NULL; + const char *object_path; + + if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(oas)"))) + return; + + g_variant_get (parameters, + "(&o^a&s)", + &object_path, + &interfaces); + + log_context = "interfaces-removed"; + changed = _dbus_handle_interface_removed (self, log_context, object_path, NULL, interfaces); + goto out; } + return; + +out: if (changed) _dbus_handle_changes (self, log_context, TRUE); } @@ -5143,7 +5177,7 @@ nm_client_add_and_activate_connection2_finish (NMClient *client, { return NM_ACTIVE_CONNECTION (_request_wait_finish (client, result, - nm_client_add_connection2, + nm_client_add_and_activate_connection2, out_result, error)); } @@ -6512,12 +6546,13 @@ _init_fetch_all (NMClient *self) priv->get_managed_objects_cancellable = g_cancellable_new (); - priv->dbsid_nm_object_manager = nm_dbus_connection_signal_subscribe_object_manager (priv->dbus_connection, - priv->name_owner, - "/org/freedesktop", - _dbus_managed_objects_changed_cb, - self, - NULL); + priv->dbsid_nm_object_manager = nm_dbus_connection_signal_subscribe_object_manager_plain (priv->dbus_connection, + priv->name_owner, + "/org/freedesktop", + NULL, + _dbus_managed_objects_changed_cb, + self, + NULL); priv->dbsid_dbus_properties_properties_changed = nm_dbus_connection_signal_subscribe_properties_changed (priv->dbus_connection, priv->name_owner, @@ -7398,6 +7433,18 @@ constructed (GObject *object) NML_NMCLIENT_LOG_D (self, "new NMClient instance"); } +static inline gboolean +_dispose_cleanup_context_busy_watcher_cb (gpointer user_data) +{ + nm_auto_unref_gmaincontext GMainContext *context = NULL; + gs_unref_object GObject *context_busy_watcher = NULL; + + nm_utils_user_data_unpack (user_data, &context, &context_busy_watcher); + + nm_assert (G_IS_OBJECT (context_busy_watcher)); + return G_SOURCE_REMOVE; +} + static void dispose (GObject *object) { @@ -7446,6 +7493,46 @@ dispose (GObject *object) nm_clear_pointer (&priv->udev, udev_unref); + if ( priv->context_busy_watcher + && priv->dbus_context) { + GSource *cleanup_source; + + /* Technically, we cancelled all pending actions (and these actions + * (GTask) keep the context_busy_watcher object alive). Also, we passed + * no destroy notify to g_dbus_connection_signal_subscribe(). + * That means, there should be no other unaccounted GSource'es left. + * + * However, we really need to be sure that the context_busy_watcher's + * lifetime matches the time that the context is busy. That is especially + * important with synchronous initialization, where the context-busy-watcher + * keeps the inner GMainContext integrated in the caller's. + * We must not g_source_destroy() that integration too early. + * + * So to be really sure all this is given, always schedule one last + * cleanup idle action with low priority. This should be the last + * thing related to this instance that keeps the context busy. + * + * Note that we could also *not* take a reference on priv->dbus_context + * and unref priv->context_busy_watcher via the GDestroyNotify. That would + * allow for the context to be wrapped up early, and when the last user + * gives up the reference to the context, the destroy notify could complete + * without even invoke the idle handler. However, that destroy notify may + * not be called in the right thread. So, we want to be sure that we unref + * the context-busy-watcher in the right context. Hence, we always take an + * additional reference and always cleanup in the idle handler. This means: + * the user *MUST* always keep iterating the context after NMClient got destroyed. + * But that is not a severe limitation, because the user anyway must be prepared + * to do that. That is because in many cases it is necessary anyway (and the user + * wouldn't know a priory when not). This way, it is just always necessary. */ + cleanup_source = nm_g_idle_source_new (G_PRIORITY_LOW + 10, + _dispose_cleanup_context_busy_watcher_cb, + nm_utils_user_data_pack (g_main_context_ref (priv->dbus_context), + g_steal_pointer (&priv->context_busy_watcher)), + NULL); + g_source_attach (cleanup_source, priv->dbus_context); + g_source_unref (cleanup_source); + } + nm_clear_pointer (&priv->dbus_context, g_main_context_unref); nm_clear_pointer (&priv->main_context, g_main_context_unref); |