core: correctly handle pre-activation dependency failure (rh #1069695)
Dependencies may fail before the activation actually starts, like when a software device gets removed while the activation is scheduled but before it has started. In these cases, the activation request should fail.
This commit is contained in:
@@ -308,20 +308,29 @@ device_state_changed (NMActiveConnection *active,
|
|||||||
NMActiveConnectionState cur_ac_state = nm_active_connection_get_state (active);
|
NMActiveConnectionState cur_ac_state = nm_active_connection_get_state (active);
|
||||||
NMActiveConnectionState ac_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
|
NMActiveConnectionState ac_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
|
||||||
|
|
||||||
/* Ignore state changes when this activation request is not yet active, but
|
/* Decide which device state changes to handle when this active connection
|
||||||
* handle the DISCONNECTED state correctly. The device clears the
|
* is not the device's current request. Two cases here: (a) the AC is
|
||||||
* activation request before sending the state change signal so this
|
* pending and not yet active, and (b) the AC was active but the device is
|
||||||
* must be special-cased to ensure the activation request is deactivated.
|
* entering DISCONNECTED state (which clears the device's current AC before
|
||||||
|
* emitting the state change signal).
|
||||||
*/
|
*/
|
||||||
if (NM_ACTIVE_CONNECTION (nm_device_get_act_request (device)) != active) {
|
if (NM_ACTIVE_CONNECTION (nm_device_get_act_request (device)) != active) {
|
||||||
if (new_state != NM_DEVICE_STATE_DISCONNECTED)
|
/* Some other request is activating; this one must be pending */
|
||||||
|
if (new_state >= NM_DEVICE_STATE_PREPARE)
|
||||||
return;
|
return;
|
||||||
|
else if (new_state == NM_DEVICE_STATE_DISCONNECTED) {
|
||||||
|
/* This request hasn't started activating yet; the device is
|
||||||
|
* disconnecting and cleaning up a previous activation request.
|
||||||
|
*/
|
||||||
if (cur_ac_state < NM_ACTIVE_CONNECTION_STATE_ACTIVATING)
|
if (cur_ac_state < NM_ACTIVE_CONNECTION_STATE_ACTIVATING)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Catch device disconnections after this request has been active */
|
/* Catch device disconnections after this request has been active */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* All states < DISCONNECTED are fatal and handled */
|
||||||
|
}
|
||||||
|
|
||||||
/* Set NMActiveConnection state based on the device's state */
|
/* Set NMActiveConnection state based on the device's state */
|
||||||
switch (new_state) {
|
switch (new_state) {
|
||||||
case NM_DEVICE_STATE_PREPARE:
|
case NM_DEVICE_STATE_PREPARE:
|
||||||
|
@@ -2611,7 +2611,17 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
|
|||||||
|
|
||||||
device = nm_active_connection_get_device (active);
|
device = nm_active_connection_get_device (active);
|
||||||
if (!device) {
|
if (!device) {
|
||||||
g_assert (connection_needs_virtual_device (connection));
|
if (!connection_needs_virtual_device (connection)) {
|
||||||
|
NMSettingConnection *s_con = nm_connection_get_setting_connection (connection);
|
||||||
|
|
||||||
|
g_assert (s_con);
|
||||||
|
g_set_error (error,
|
||||||
|
NM_MANAGER_ERROR,
|
||||||
|
NM_MANAGER_ERROR_UNKNOWN_DEVICE,
|
||||||
|
"Unsupported virtual interface type '%s'",
|
||||||
|
nm_setting_connection_get_connection_type (s_con));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
device = system_create_virtual_device (self, connection);
|
device = system_create_virtual_device (self, connection);
|
||||||
if (!device) {
|
if (!device) {
|
||||||
@@ -2721,6 +2731,17 @@ _internal_activate_generic (NMManager *self, NMActiveConnection *active, GError
|
|||||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||||
gboolean success = FALSE;
|
gboolean success = FALSE;
|
||||||
|
|
||||||
|
/* Ensure activation request is still valid, eg that its device hasn't gone
|
||||||
|
* away or that some other dependency has not failed.
|
||||||
|
*/
|
||||||
|
if (nm_active_connection_get_state (active) >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
NM_MANAGER_ERROR,
|
||||||
|
NM_MANAGER_ERROR_DEPENDENCY_FAILED,
|
||||||
|
"Activation failed because dependencies failed.");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (NM_IS_VPN_CONNECTION (active))
|
if (NM_IS_VPN_CONNECTION (active))
|
||||||
success = _internal_activate_vpn (self, active, error);
|
success = _internal_activate_vpn (self, active, error);
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user