From 7913275b02c60803f21609168f9c16d2f2a4be2f Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Thu, 16 Jul 2020 11:57:14 +0200 Subject: [PATCH 1/2] manager: fix race condition when resuming from sleep If the device state change (to disconnected or unmanaged) triggered by a sleep event happens after the wake, the devices becomes wrongly unmanaged and it's necessary to manually manage it again, or restart NM. During the wake event we should disconnect the device_sleep_cb() callback for all devices because we don't want to react to state changes anymore; in particular we don't need to detect when the device becomes disconnected to unmanage it. (cherry picked from commit fe2d93980bd5b61c55a8b65a55f7aad35042e691) (cherry picked from commit 971897195a8218cb0ec08ae95a7210fce73f0b03) --- src/nm-manager.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index bbe501259f..6ff3bd7af4 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -6035,8 +6035,9 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed) } else { _LOGD (LOGD_SUSPEND, "sleep: %s...", waking_from_suspend ? "waking up" : "re-enabling"); + sleep_devices_clear (self); + if (waking_from_suspend) { - sleep_devices_clear (self); c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { if (nm_device_is_software (device)) continue; From ecb134ac349a0bf6582833253b6d453d6bf997de Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Thu, 16 Jul 2020 11:58:20 +0200 Subject: [PATCH 2/2] policy: block connection from autoconnect in case of failed dependency A connection that fails due to dependency-failed is not able to reconnect until the master connection activates again; when this happens, the master clears the blocked reason for all its slaves in activate_slave_connections() and tries to reconnect them. For this to work, the slave should be marked as blocked when it fails with dependency-failed. (cherry picked from commit 725fed01cf7c8508cf426897340b2a4113406aab) (cherry picked from commit e1755048e35aca682c7d0d233122d4ddaf3bb089) --- src/nm-policy.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/nm-policy.c b/src/nm-policy.c index 2a9f6c051f..ed3f8b20d1 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -1789,7 +1789,7 @@ device_state_changed (NMDevice *device, if ( sett_conn && old_state >= NM_DEVICE_STATE_PREPARE && old_state <= NM_DEVICE_STATE_ACTIVATED) { - gboolean block_no_secrets = FALSE; + gboolean blocked = FALSE; int tries; guint64 con_v; @@ -1809,15 +1809,32 @@ device_state_changed (NMDevice *device, */ con_v = nm_settings_connection_get_last_secret_agent_version_id (sett_conn); if ( con_v == 0 - || con_v == nm_agent_manager_get_agent_version_id (priv->agent_mgr)) - block_no_secrets = TRUE; + || con_v == nm_agent_manager_get_agent_version_id (priv->agent_mgr)) { + _LOGD (LOGD_DEVICE, "connection '%s' now blocked from autoconnect due to no secrets", + nm_settings_connection_get_id (sett_conn)); + nm_settings_connection_autoconnect_blocked_reason_set (sett_conn, + NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS, + TRUE); + blocked = TRUE; + } + } else if (nm_device_state_reason_check (reason) == NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED) { + /* A connection that fails due to dependency-failed is not + * able to reconnect until the master connection activates + * again; when this happens, the master clears the blocked + * reason for all its slaves in activate_slave_connections() + * and tries to reconnect them. For this to work, the slave + * should be marked as blocked when it fails with + * dependency-failed. + */ + _LOGD (LOGD_DEVICE, "connection '%s' now blocked from autoconnect due to failed dependency", + nm_settings_connection_get_id (sett_conn)); + nm_settings_connection_autoconnect_blocked_reason_set (sett_conn, + NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED, + TRUE); + blocked = TRUE; } - if (block_no_secrets) { - _LOGD (LOGD_DEVICE, "connection '%s' now blocked from autoconnect due to no secrets", - nm_settings_connection_get_id (sett_conn)); - nm_settings_connection_autoconnect_blocked_reason_set (sett_conn, NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS, TRUE); - } else { + if (!blocked) { tries = nm_settings_connection_autoconnect_retries_get (sett_conn); if (tries > 0) { _LOGD (LOGD_DEVICE, "connection '%s' failed to autoconnect; %d tries left",