From 4d2957b3ae930eb49078254eb799caeba2bbe370 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 11 Feb 2011 21:29:41 -0600 Subject: [PATCH] settings: fix NMSettingsConnection D-Bus Remove signal emission We can't unregister the object with the bus during the remove signal, because dbus-glib doesn't send the signal out over the bus until late in the signal emission process, after we've unregisterd the object. Thus the signal doesn't go out. Fix that. --- src/settings/nm-settings-connection.c | 25 +++++++++++++++++++ src/settings/nm-settings-connection.h | 2 ++ src/settings/nm-settings.c | 30 +++++++++++++++++------ system-settings/plugins/ifcfg-rh/plugin.c | 4 +-- system-settings/plugins/ifnet/plugin.c | 4 +-- system-settings/plugins/keyfile/plugin.c | 4 +-- 6 files changed, 56 insertions(+), 13 deletions(-) diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index 5c7a14273d..4c059df862 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -68,6 +68,7 @@ enum { enum { UPDATED, REMOVED, + UNREGISTER, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; @@ -1181,6 +1182,20 @@ impl_settings_connection_get_secrets (NMSettingsConnection *self, /**************************************************************/ +void +nm_settings_connection_signal_remove (NMSettingsConnection *self) +{ + /* Emit removed first */ + g_signal_emit_by_name (self, NM_SETTINGS_CONNECTION_REMOVED); + + /* And unregistered last to ensure the removed signal goes out before + * we take the connection off the bus. + */ + g_signal_emit_by_name (self, "unregister"); +} + +/**************************************************************/ + static void nm_settings_connection_init (NMSettingsConnection *self) { @@ -1314,6 +1329,16 @@ nm_settings_connection_class_init (NMSettingsConnectionClass *class) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + /* Not exported */ + signals[UNREGISTER] = + g_signal_new ("unregister", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (class), &dbus_glib_nm_settings_connection_object_info); } diff --git a/src/settings/nm-settings-connection.h b/src/settings/nm-settings-connection.h index 643b1756ed..190923c9fb 100644 --- a/src/settings/nm-settings-connection.h +++ b/src/settings/nm-settings-connection.h @@ -114,6 +114,8 @@ gboolean nm_settings_connection_is_visible (NMSettingsConnection *self); void nm_settings_connection_recheck_visibility (NMSettingsConnection *self); +void nm_settings_connection_signal_remove (NMSettingsConnection *self); + G_END_DECLS #endif /* NM_SETTINGS_CONNECTION_H */ diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index 7f705d9f06..83c45b3a27 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -587,11 +587,11 @@ load_plugins (NMSettings *self, const char *plugins, GError **error) #define REMOVED_ID_TAG "removed-id-tag" #define UPDATED_ID_TAG "updated-id-tag" #define VISIBLE_ID_TAG "visible-id-tag" +#define UNREG_ID_TAG "unreg-id-tag" static void connection_removed (NMSettingsConnection *obj, gpointer user_data) { - NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (user_data); GObject *connection = G_OBJECT (obj); guint id; @@ -614,20 +614,31 @@ connection_removed (NMSettingsConnection *obj, gpointer user_data) if (id) g_signal_handler_disconnect (connection, id); - /* Unregister the connection with D-Bus and forget about it */ - dbus_g_connection_unregister_g_object (priv->bus, connection); + /* Forget about the connection internall */ g_hash_table_remove (NM_SETTINGS_GET_PRIVATE (user_data)->connections, (gpointer) nm_connection_get_path (NM_CONNECTION (connection))); /* Re-emit for listeners like NMPolicy */ - g_signal_emit (NM_SETTINGS (user_data), - signals[CONNECTION_REMOVED], - 0, - connection); + g_signal_emit (NM_SETTINGS (user_data), signals[CONNECTION_REMOVED], 0, connection); g_object_unref (connection); } +static void +connection_unregister (NMSettingsConnection *obj, gpointer user_data) +{ + NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (user_data); + GObject *connection = G_OBJECT (obj); + guint id; + + /* Make sure it's unregistered from the bus now that's removed */ + dbus_g_connection_unregister_g_object (priv->bus, connection); + + id = GPOINTER_TO_UINT (g_object_get_data (connection, UNREG_ID_TAG)); + if (id) + g_signal_handler_disconnect (connection, id); +} + static void connection_updated (NMSettingsConnection *connection, gpointer user_data) { @@ -689,6 +700,11 @@ claim_connection (NMSettings *self, self); g_object_set_data (G_OBJECT (connection), REMOVED_ID_TAG, GUINT_TO_POINTER (id)); + id = g_signal_connect (connection, "unregister", + G_CALLBACK (connection_unregister), + self); + g_object_set_data (G_OBJECT (connection), UNREG_ID_TAG, GUINT_TO_POINTER (id)); + id = g_signal_connect (connection, NM_SETTINGS_CONNECTION_UPDATED, G_CALLBACK (connection_updated), self); diff --git a/system-settings/plugins/ifcfg-rh/plugin.c b/system-settings/plugins/ifcfg-rh/plugin.c index 24e271df3b..3e2e034628 100644 --- a/system-settings/plugins/ifcfg-rh/plugin.c +++ b/system-settings/plugins/ifcfg-rh/plugin.c @@ -221,7 +221,7 @@ remove_connection (SCPluginIfcfg *self, NMIfcfgConnection *connection) g_object_ref (connection); g_hash_table_remove (priv->connections, path); - g_signal_emit_by_name (connection, NM_SETTINGS_CONNECTION_REMOVED); + nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection)); g_object_unref (connection); /* Emit unmanaged changes _after_ removing the connection */ @@ -294,7 +294,7 @@ connection_new_or_changed (SCPluginIfcfg *self, * been removed, and notify the settings service by signalling that * unmanaged specs have changed. */ - g_signal_emit_by_name (existing, NM_SETTINGS_CONNECTION_REMOVED); + nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (existing)); g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); } } else { diff --git a/system-settings/plugins/ifnet/plugin.c b/system-settings/plugins/ifnet/plugin.c index f7cc6b3941..f71acf6cf1 100644 --- a/system-settings/plugins/ifnet/plugin.c +++ b/system-settings/plugins/ifnet/plugin.c @@ -287,7 +287,7 @@ reload_connections (gpointer config) PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Auto refreshing %s", conn_name); /* Remove and re-add to disconnect and reconnect with new settings */ - g_signal_emit_by_name (old, NM_SETTINGS_CONNECTION_REMOVED); + nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (old)); g_hash_table_remove (priv->config_connections, conn_name); g_hash_table_insert (priv->config_connections, g_strdup (conn_name), new); if (is_managed (conn_name)) @@ -313,7 +313,7 @@ reload_connections (gpointer config) g_hash_table_iter_init (&iter, priv->config_connections); while (g_hash_table_iter_next (&iter, &key, &value)) { if (!g_hash_table_lookup (new_conn_names, key)) { - g_signal_emit_by_name (value, NM_SETTINGS_CONNECTION_REMOVED); + nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (value)); g_hash_table_remove (priv->config_connections, key); } } diff --git a/system-settings/plugins/keyfile/plugin.c b/system-settings/plugins/keyfile/plugin.c index 2c2494e4f2..68f51dc4ae 100644 --- a/system-settings/plugins/keyfile/plugin.c +++ b/system-settings/plugins/keyfile/plugin.c @@ -143,7 +143,7 @@ update_connection_settings_commit_cb (NMSettingsConnection *orig, GError *error, error ? error->code : -1); g_clear_error (&error); - g_signal_emit_by_name (orig, NM_SETTINGS_CONNECTION_REMOVED); + nm_settings_connection_signal_remove (orig); } } @@ -169,7 +169,7 @@ remove_connection (SCPluginKeyfile *self, /* Removing from the hash table should drop the last reference */ g_object_ref (connection); g_hash_table_remove (SC_PLUGIN_KEYFILE_GET_PRIVATE (self)->hash, name); - g_signal_emit_by_name (connection, NM_SETTINGS_CONNECTION_REMOVED); + nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection)); g_object_unref (connection); }