summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-04-23 14:28:27 +0200
committerThomas Haller <thaller@redhat.com>2020-04-24 13:58:46 +0200
commit27e2d51abc52e203d22d63398558e4a0edd8b019 (patch)
treeb9e223a46740e1c3c52c9b12f2136e9cc521fab5
parentcd5157a0c38adb20eb290a145888703b3d09dd4f (diff)
downloadNetworkManager-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.c57
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);
}