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.
This commit is contained in:
Dan Williams 2011-02-11 21:29:41 -06:00
parent e386ebef39
commit 4d2957b3ae
6 changed files with 56 additions and 13 deletions

View file

@ -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);
}

View file

@ -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 */

View file

@ -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);

View file

@ -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 {

View file

@ -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);
}
}

View file

@ -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);
}