From 42b9e8283969a851751a9eff5c767ae99d717156 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 3 Nov 2014 23:25:23 +0100 Subject: [PATCH] libnm: Complete activation when ActiveConnection abruptly disappears A NMActiveConnection may disappear before a match with NMDevice is found. In such case recheck_pending_activations() would never call the activation callback and the client would hang indefinitely: libnm-Message: PC: (0x95bf088) NMManager:active-connections => '['/org/freedesktop/NetworkManager/ActiveConnection/225']' (ao / NMActiveConnection) libnm-Message: PC: (0x95bf088) NMManager:activating-connection => ''/'' (o / NMActiveConnection) libnm-Message: PC: (0x95d0a28) NMActiveConnection:state => '4' (u) libnm-Message: PC: (0x95d0a28) NMActiveConnection:devices => '[]' (ao / NMDevice) libnm-Message: PC: (0x95bf088) NMManager:active-connections => '[]' (ao / NMActiveConnection) *hang* Let's listen for active-connection-removed and tear down the activation with an error if the removed connection is one we're activating. --- libnm/nm-manager.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libnm/nm-manager.c b/libnm/nm-manager.c index 8d78d221bc..fc558620c7 100644 --- a/libnm/nm-manager.c +++ b/libnm/nm-manager.c @@ -743,6 +743,8 @@ typedef struct { char *new_connection_path; } ActivateInfo; +static void active_removed (NMObject *object, NMActiveConnection *active, gpointer user_data); + static void activate_info_complete (ActivateInfo *info, NMActiveConnection *active, @@ -750,6 +752,7 @@ activate_info_complete (ActivateInfo *info, { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (info->manager); + g_signal_handlers_disconnect_by_func (info->manager, G_CALLBACK (active_removed), info); if (active) g_simple_async_result_set_op_res_gpointer (info->simple, g_object_ref (active), g_object_unref); else @@ -836,6 +839,22 @@ activation_cancelled (GCancellable *cancellable, g_clear_error (&error); } +static void +active_removed (NMObject *object, NMActiveConnection *active, gpointer user_data) +{ + ActivateInfo *info = user_data; + GError *error = NULL; + + if (strcmp (info->active_path, nm_object_get_path (NM_OBJECT (active)))) + return; + + error = g_error_new_literal (NM_CLIENT_ERROR, + NM_CLIENT_ERROR_FAILED, + _("Active connection could not be attached to the device")); + activate_info_complete (info, NULL, error); + g_clear_error (&error); +} + static void activate_cb (GObject *object, GAsyncResult *result, @@ -852,6 +871,9 @@ activate_cb (GObject *object, G_CALLBACK (activation_cancelled), info); } + g_signal_connect (info->manager, "active-connection-removed", + G_CALLBACK (active_removed), info); + recheck_pending_activations (info->manager); } else { g_dbus_error_strip_remote_error (error);