diff options
author | Thomas Haller <thaller@redhat.com> | 2020-04-23 14:28:27 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2020-04-24 13:58:46 +0200 |
commit | 27e2d51abc52e203d22d63398558e4a0edd8b019 (patch) | |
tree | b9e223a46740e1c3c52c9b12f2136e9cc521fab5 | |
parent | cd5157a0c38adb20eb290a145888703b3d09dd4f (diff) | |
download | NetworkManager-27e2d51abc52e203d22d63398558e4a0edd8b019.tar.gz |
cli: repeatedly trigger Wi-Fi scans while waiting for scan result
NetworkManager will reject scan requests, if it is currently scanning.
That is very wrong. Even if NetworkManager wants to ratelimit scan
requests or not scan at critical moments, it should never reject a
request, but remember and start scanning as soon as it can.
That should be fixed.
But regardless, also nmcli can do better.
If you issue
$ nmcli device wifi list --rescan yes
once, it works as expected.
If you issue it again right after, the scan request of nmcli will be
rejected. But nmcli cannot just merely complete and print the result.
Instead, it will wait in the hope that a scan result will be present
soon. But if the request was simply rejected, then the result will
never come, and nmcli hangs for the 15 seconds timeout.
Instead, repeatedly re-trigger scan requests, in the hope that as soon
as possible we will be ready.
-rw-r--r-- | clients/cli/devices.c | 57 |
1 files changed, 50 insertions, 7 deletions
diff --git a/clients/cli/devices.c b/clients/cli/devices.c index 4ea4e772e4..7031b43756 100644 --- a/clients/cli/devices.c +++ b/clients/cli/devices.c @@ -2978,6 +2978,24 @@ wifi_last_scan_updated (GObject *gobject, GParamSpec *pspec, gpointer user_data) wifi_list_finish (user_data, FALSE); } +static void wifi_list_rescan_cb (GObject *source_object, GAsyncResult *res, gpointer user_data); + +static void +wifi_list_rescan_retry_cb (gpointer user_data, + GCancellable *cancellable) +{ + WifiListData *wifi_list_data; + + if (g_cancellable_is_cancelled (cancellable)) + return; + + wifi_list_data = user_data; + nm_device_wifi_request_scan_async (wifi_list_data->wifi, + wifi_list_data->scan_cancellable, + wifi_list_rescan_cb, + wifi_list_data); +} + static void wifi_list_rescan_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { @@ -2985,22 +3003,47 @@ wifi_list_rescan_cb (GObject *source_object, GAsyncResult *res, gpointer user_da gs_free_error GError *error = NULL; WifiListData *wifi_list_data; gboolean force_finished; + gboolean done; nm_device_wifi_request_scan_finish (wifi, res, &error); if (nm_utils_error_is_cancelled (error)) return; + wifi_list_data = user_data; + if (g_error_matches (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ALLOWED)) { - /* This likely means that scanning is already in progress. There's - * a good chance we'll get updated results soon; wait for them. */ - force_finished = FALSE; - } else if (error) + if (nm_device_get_state (NM_DEVICE (wifi)) < NM_DEVICE_STATE_DISCONNECTED) { + /* the device is either unmanaged or unavailable. + * + * If it's unmanaged, we don't expect any scan result and are done. + * If it's unavailable, that usually means that we wait for wpa_supplicant + * to start. In that case, also quit (without scan results). */ + force_finished = TRUE; + done = TRUE; + } else { + /* This likely means that scanning is already in progress. There's + * a good chance we'll get updated results soon; wait for them. + * + * But also, NetworkManager ratelimits (and rejects requests). That + * means, possibly we were just ratelimited, so waiting will not lead + * to a new scan result. Instead, repeatedly ask new scans... */ + nm_utils_invoke_on_timeout (1000, + wifi_list_data->scan_cancellable, + wifi_list_rescan_retry_cb, + wifi_list_data); + force_finished = FALSE; + done = FALSE; + } + } else if (error) { force_finished = TRUE; - else + done = TRUE; + } else { force_finished = FALSE; + done = TRUE; + } - wifi_list_data = user_data; - g_clear_object (&wifi_list_data->scan_cancellable); + if (done) + g_clear_object (&wifi_list_data->scan_cancellable); wifi_list_finish (wifi_list_data, force_finished); } |