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) <brauner@kernel.org>
This commit is contained in:
Christian Brauner
2026-04-24 14:39:25 +02:00
parent b75b6041e0
commit 1dbfab132a
+8 -5
View 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);
}