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.
This commit is contained in:
Lubomir Rintel 2014-11-03 23:25:23 +01:00 committed by Jiří Klimeš
parent b4fe3b7cd9
commit 42b9e82839

View file

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