core: fix handling of ActiveConnections on Policy dispose()

The manager has already disposed of the ActiveConnections by the time
the Policy is disposed, but the manager wasn't clearing the
active_connections list, so the Policy got a stale list of freed
objects.  Next, the manager wasn't always emitting ACTIVE_CONNECTION_REMOVED
when disposing of ActiveConnections, which the Policy listens to
for cleanup.  This lead to warnings on shutdown when the Policy
attempted to clean up for already disposed objects

Fix all this by ensuring the Manager signals when removing
ActiveConnections, which the Policy then uses to clean up
it's stuff, and ensuring the manager properly cleans up its
ActiveConnection list.
This commit is contained in:
Dan Williams 2013-08-30 17:57:56 -05:00
parent c6ba3ca51b
commit 1a42e764d4
2 changed files with 17 additions and 9 deletions

View file

@ -330,6 +330,14 @@ static void active_connection_state_changed (NMActiveConnection *active,
GParamSpec *pspec,
NMManager *self);
static void
active_connection_removed (NMManager *self, NMActiveConnection *active)
{
g_signal_emit (self, signals[ACTIVE_CONNECTION_REMOVED], 0, active);
g_signal_handlers_disconnect_by_func (active, active_connection_state_changed, self);
g_object_unref (active);
}
static gboolean
_active_connection_cleanup (gpointer user_data)
{
@ -347,9 +355,7 @@ _active_connection_cleanup (gpointer user_data)
iter = iter->next;
if (nm_active_connection_get_state (ac) == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) {
priv->active_connections = g_slist_remove (priv->active_connections, ac);
g_signal_emit (self, signals[ACTIVE_CONNECTION_REMOVED], 0, ac);
g_signal_handlers_disconnect_by_func (ac, active_connection_state_changed, self);
g_object_unref (ac);
active_connection_removed (self, ac);
changed = TRUE;
}
}
@ -4554,11 +4560,10 @@ dispose (GObject *object)
priv->ac_cleanup_id = 0;
}
for (iter = priv->active_connections; iter; iter = g_slist_next (iter)) {
g_signal_handlers_disconnect_by_func (iter->data, active_connection_state_changed, object);
g_object_unref (iter->data);
}
for (iter = priv->active_connections; iter; iter = g_slist_next (iter))
active_connection_removed (manager, NM_ACTIVE_CONNECTION (iter->data));
g_slist_free (priv->active_connections);
priv->active_connections = NULL;
g_clear_object (&priv->primary_connection);
g_clear_object (&priv->activating_connection);

View file

@ -2182,9 +2182,12 @@ dispose (GObject *object)
}
g_clear_pointer (&priv->dev_ids, g_slist_free);
/* The manager should have disposed of ActiveConnections already, which
* will have called active_connection_removed() and thus we don't need
* to clean anything up. Assert that this is TRUE.
*/
connections = nm_manager_get_active_connections (priv->manager);
for (iter = connections; iter; iter = g_slist_next (iter))
active_connection_removed (priv->manager, NM_ACTIVE_CONNECTION (iter->data), policy);
g_assert (connections == NULL);
if (priv->reset_retries_id) {
g_source_remove (priv->reset_retries_id);