vpn: stop all connections of a service outside of dispose

Future patches will allow blocking dispatcher calls, which we
don't want to happen when deactivating a VPN connection during
normal operation.  So move code that stops VPN connections outside
of the VPNService object's dispose() function and require the object
that owns the VPNService (the VPNManager) to stop connections at the
right times.

When quitting, blocking calls are acceptable (because NetworkManager's
D-Bus interface is no longer useful, plus we can't easily schedule
callbacks because no mainloop is running), so it's ok to stop
connections from NMVPNManager:dispose.
This commit is contained in:
Dan Williams 2014-05-19 18:38:04 -05:00
parent fbb38ebefe
commit d1095e00cb
3 changed files with 29 additions and 12 deletions

View file

@ -186,7 +186,7 @@ vpn_dir_changed (GFileMonitor *monitor,
const char *service_name = nm_vpn_service_get_dbus_service (service);
/* Stop active VPN connections and destroy the service */
nm_vpn_service_connections_stop (service, TRUE,
nm_vpn_service_stop_connections (service, FALSE,
NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED);
nm_log_info (LOGD_VPN, "VPN: unloaded %s", service_name);
g_hash_table_remove (priv->services, service_name);
@ -257,6 +257,21 @@ nm_vpn_manager_init (NMVPNManager *self)
}
}
static void
stop_all_services (NMVPNManager *self)
{
NMVPNManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self);
GHashTableIter iter;
NMVPNService *service;
g_hash_table_iter_init (&iter, priv->services);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &service)) {
nm_vpn_service_stop_connections (service,
TRUE,
NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED);
}
}
static void
dispose (GObject *object)
{
@ -270,6 +285,7 @@ dispose (GObject *object)
}
if (priv->services) {
stop_all_services (NM_VPN_MANAGER (object));
g_hash_table_destroy (priv->services);
priv->services = NULL;
}

View file

@ -138,8 +138,8 @@ connection_vpn_state_changed (NMVPNConnection *connection,
}
void
nm_vpn_service_connections_stop (NMVPNService *service,
gboolean fail,
nm_vpn_service_stop_connections (NMVPNService *service,
gboolean quitting,
NMVPNConnectionStateReason reason)
{
NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (service);
@ -157,7 +157,8 @@ nm_vpn_service_connections_stop (NMVPNService *service,
NMVPNConnection *vpn = NM_VPN_CONNECTION (iter->data);
g_signal_handlers_disconnect_by_func (vpn, G_CALLBACK (connection_vpn_state_changed), service);
nm_vpn_connection_stop (vpn, fail, reason);
/* Quitting terminates the VPN cleanly, otherwise failure is assumed */
nm_vpn_connection_stop (vpn, quitting ? FALSE : TRUE, reason);
g_object_unref (vpn);
}
g_clear_pointer (&priv->pending, g_slist_free);
@ -185,7 +186,7 @@ _daemon_exec_timeout (gpointer data)
nm_log_warn (LOGD_VPN, "VPN service '%s' start timed out", priv->name);
priv->start_timeout = 0;
nm_vpn_service_connections_stop (self, TRUE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT);
nm_vpn_service_stop_connections (self, FALSE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT);
return G_SOURCE_REMOVE;
}
@ -218,7 +219,7 @@ nm_vpn_service_daemon_exec (NMVPNService *service, GError **error)
NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_SERVICE_START_FAILED,
"%s", spawn_error ? spawn_error->message : "unknown g_spawn_async() error");
nm_vpn_service_connections_stop (service, TRUE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED);
nm_vpn_service_stop_connections (service, FALSE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED);
if (spawn_error)
g_error_free (spawn_error);
}
@ -333,7 +334,7 @@ _name_owner_changed (NMDBusManager *mgr,
/* service went away */
priv->service_running = FALSE;
nm_log_info (LOGD_VPN, "VPN service '%s' disappeared", priv->name);
nm_vpn_service_connections_stop (service, TRUE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED);
nm_vpn_service_stop_connections (service, FALSE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED);
}
}
@ -359,9 +360,9 @@ dispose (GObject *object)
priv->start_timeout = 0;
}
nm_vpn_service_connections_stop (NM_VPN_SERVICE (object),
FALSE,
NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED);
/* VPNService owner is required to stop connections before releasing */
g_assert (priv->active == NULL);
g_assert (priv->pending == NULL);
g_signal_handlers_disconnect_by_func (nm_dbus_manager_get (),
G_CALLBACK (_name_owner_changed),

View file

@ -56,8 +56,8 @@ gboolean nm_vpn_service_activate (NMVPNService *service,
NMVPNConnection *vpn,
GError **error);
void nm_vpn_service_connections_stop (NMVPNService *service,
gboolean fail,
void nm_vpn_service_stop_connections (NMVPNService *service,
gboolean quitting,
NMVPNConnectionStateReason reason);
#endif /* NM_VPN_VPN_SERVICE_H */