]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
vmspawn-qmp: keep the event loop running on post-setup QMP failures
authorChristian Brauner <brauner@kernel.org>
Tue, 21 Apr 2026 22:29:37 +0000 (00:29 +0200)
committerChristian Brauner <brauner@kernel.org>
Fri, 24 Apr 2026 12:39:25 +0000 (14:39 +0200)
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) <brauner@kernel.org>
src/vmspawn/vmspawn-qmp.c

index cfa887e1223a3cd5b3dca46fae71be64e0513642..7eff45f5e933fb57a2c366f9e602084c6c7f3cd9 100644 (file)
@@ -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);
         }