From: Christian Brauner Date: Tue, 21 Apr 2026 22:29:37 +0000 (+0200) Subject: vmspawn-qmp: keep the event loop running on post-setup QMP failures X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1dbfab132ae10fed5c91c6e09a3c3450e01ef261;p=thirdparty%2Fsystemd.git vmspawn-qmp: keep the event loop running on post-setup QMP failures on_qmp_complete tears the event loop down on any QMP error, which is the right behaviour while we're still building the VM (a missing device means we'd boot a half-configured guest). Once the boot-time setup is finished and the guest is running, killing the event loop on a QMP error means a single failed runtime command (e.g. a hotplug device_add that the guest rejects) takes the whole VM down. Consult bridge->setup_done — already flipped at the end of boot setup — and skip the event-loop exit once it's set; logging is sufficient post-setup. The bridge is fetched from the qmp client userdata, the same pointer the rest of the file uses. Signed-off-by: Christian Brauner (Amutable) --- diff --git a/src/vmspawn/vmspawn-qmp.c b/src/vmspawn/vmspawn-qmp.c index cfa887e1223..7eff45f5e93 100644 --- a/src/vmspawn/vmspawn-qmp.c +++ b/src/vmspawn/vmspawn-qmp.c @@ -103,9 +103,7 @@ void machine_config_done(MachineConfig *c) { vsock_info_done(&c->vsock); } -/* Generic async QMP setup-completion callback. The userdata argument carries the - * command name (as a string literal) for logging. On failure, request a clean - * event loop exit so vmspawn shuts down instead of running a VM with missing devices. */ +/* Generic completion callback; userdata is a string literal label. Exits the event loop on boot-time failures. */ static int on_qmp_complete( QmpClient *client, sd_json_variant *result, @@ -113,12 +111,17 @@ static int on_qmp_complete( int error, void *userdata) { - const char *label = ASSERT_PTR(userdata); - assert(client); + VmspawnQmpBridge *bridge = ASSERT_PTR(qmp_client_get_userdata(client)); + const char *label = ASSERT_PTR(userdata); + if (error < 0) { log_error_errno(error, "%s failed: %s", label, strna(error_desc)); + + if (bridge->setup_done) + return 0; + return sd_event_exit(qmp_client_get_event(client), error); }