From d896c3fbfa02e74d214b6c300f890f058ca94015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Mon, 2 Mar 2026 12:49:18 +0100 Subject: [PATCH] nmcli: wait for `device set` async operation to finish We need to wait for it to finish so we can show error messages, if any. Also, if we don't do it, sometimes the `d set eth0 managed ...` operation fails with the following message in the daemon's log: "Unable to determine UID of the request". This is because the client's process is terminated before the daemon can check the permissions, as it needs to check the uid and gid from the client's process. (cherry picked from commit 7ee50b687a86c6cc6ecb2dd912ff58f873db5e0c) --- src/nmcli/devices.c | 58 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/src/nmcli/devices.c b/src/nmcli/devices.c index 0b0ebd1ea7..2787439ec7 100644 --- a/src/nmcli/devices.c +++ b/src/nmcli/devices.c @@ -2795,11 +2795,52 @@ do_devices_delete(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const } } +typedef struct { + NmCli *nmc; + GSource *timeout_source; +} DeviceSetCbInfo; + +static void +device_set_cb_info_finish(DeviceSetCbInfo *info) +{ + nm_clear_g_source_inst(&info->timeout_source); + g_slice_free(DeviceSetCbInfo, info); + quit(); +} + +static gboolean +device_set_timeout_cb(gpointer user_data) +{ + DeviceSetCbInfo *cb_info = user_data; + + timeout_cb(cb_info->nmc); + device_set_cb_info_finish(cb_info); + return G_SOURCE_REMOVE; +} + +static void +device_set_cb(GObject *object, GAsyncResult *result, gpointer user_data) +{ + NMDevice *device = NM_DEVICE(object); + DeviceSetCbInfo *info = (DeviceSetCbInfo *) user_data; + NmCli *nmc = info->nmc; + gs_free_error GError *error = NULL; + + /* Only 'managed' is treated asynchronously, 'autoconnect' is treated synchronously */ + if (!nm_device_set_managed_finish(device, result, &error)) { + g_string_printf(nmc->return_text, _("Error: set managed failed: %s."), error->message); + nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; + } + + device_set_cb_info_finish(info); +} + static void do_device_set(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv) { - NMDevice *device = NULL; - int i; + NMDevice *device = NULL; + DeviceSetCbInfo *cb_info = NULL; + int i; struct { int idx; gboolean value; @@ -2962,12 +3003,21 @@ do_device_set(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *ar nm_device_set_autoconnect(device, autoconnect_data.value); } if (managed_data.idx == i) { + cb_info = g_slice_new0(DeviceSetCbInfo); + cb_info->nmc = nmc; + if (nmc->timeout > 0) + cb_info->timeout_source = + nm_g_timeout_add_seconds_source(nmc->timeout, device_set_timeout_cb, cb_info); + + nmc->nowait_flag = (nmc->timeout == 0); + nmc->should_wait++; + nm_device_set_managed_async(device, managed_data.value, managed_data.flags, NULL, - NULL, - NULL); + device_set_cb, + cb_info); } } }