From 54e76ec901ad4addab06ffb56b2b0fd17b7c8284 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. --- 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 310baddd67..cfedd63435 100644 --- a/src/nmcli/devices.c +++ b/src/nmcli/devices.c @@ -2814,11 +2814,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; @@ -2981,12 +3022,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_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); } } }