--- src/qemu/qemu_capabilities.c | 192 +++++++++++++++++++++++++++---------------- 1 file changed, 120 insertions(+), 72 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 5dc3c9e..9440396 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2464,6 +2464,116 @@ cleanup: return ret; } +static virCommandPtr +virQEMUCapsInitQMPCommandNew(const char *binary, + const char *monitor, + const char *pidfile, + uid_t runUid, + gid_t runGid) +{ + virCommandPtr cmd; + + /* + * We explicitly need to use -daemonize here, rather than + * virCommandDaemonize, because we need to synchronize + * with QEMU creating its monitor socket API. Using + * daemonize guarantees control won't return to libvirt + * until the socket is present. + */ + cmd = virCommandNewArgList(binary, + "-S", + "-no-user-config", + "-nodefaults", + "-nographic", + "-M", "none", + "-qmp", monitor, + "-pidfile", pidfile, + "-daemonize", + NULL); + virCommandAddEnvPassCommon(cmd); + virCommandClearCaps(cmd); + virCommandSetGID(cmd, runGid); + virCommandSetUID(cmd, runUid); + return cmd; +} + +static int +virQEMUCapsInitQMPCommandRun(virCommandPtr cmd, + const char *binary, + const char *pidfile, + virDomainChrSourceDefPtr config, + qemuMonitorPtr *mon, + pid_t *pid) +{ + int status = 0; + virDomainObj vm; + int ret = -1; + + if (virCommandRun(cmd, &status) < 0) { + ret = -2; + goto cleanup; + } + + if (status != 0) { + VIR_DEBUG("QEMU %s exited with status %d", binary, status); + goto cleanup; + } + + if (virPidFileReadPath(pidfile, pid) < 0) { + VIR_DEBUG("Failed to read pidfile %s", pidfile); + goto cleanup; + } + + memset(&vm, 0, sizeof(vm)); + vm.pid = *pid; + + if (!(*mon = qemuMonitorOpen(&vm, config, true, &callbacks))) + goto cleanup; + + virObjectLock(*mon); + + if (qemuMonitorSetCapabilities(*mon) < 0) { + virErrorPtr err = virGetLastError(); + VIR_DEBUG("Failed to set monitor capabilities %s", + err ? err->message : "<unknown problem>"); + goto cleanup; + } + + ret = 0; +cleanup: + return ret; +} + +static void +virQEMUCapsInitQMPCommandAbort(virCommandPtr *cmd, + qemuMonitorPtr *mon, + pid_t *pid, + const char *pidfile) +{ + if (*mon) + virObjectUnlock(*mon); + qemuMonitorClose(*mon); + *mon = NULL; + + virCommandAbort(*cmd); + virCommandFree(*cmd); + *cmd = NULL; + + if (*pid != 0) { + char ebuf[1024]; + + VIR_DEBUG("Killing QMP caps process %lld", (long long) *pid); + if (virProcessKill(*pid, SIGKILL) < 0 && errno != ESRCH) + VIR_ERROR(_("Failed to kill process %lld: %s"), + (long long) *pid, + virStrerror(errno, ebuf, sizeof(ebuf))); + *pid = 0; + } + + if (pidfile) + unlink(pidfile); +} + static int virQEMUCapsInitQMP(virQEMUCapsPtr qemuCaps, const char *libDir, @@ -2475,13 +2585,11 @@ virQEMUCapsInitQMP(virQEMUCapsPtr qemuCaps, qemuMonitorPtr mon = NULL; int major, minor, micro; char *package = NULL; - int status = 0; virDomainChrSourceDef config; char *monarg = NULL; char *monpath = NULL; char *pidfile = NULL; pid_t pid = 0; - virDomainObj vm; /* the ".sock" sufix is important to avoid a possible clash with a qemu * domain called "capabilities" @@ -2507,58 +2615,15 @@ virQEMUCapsInitQMP(virQEMUCapsPtr qemuCaps, VIR_DEBUG("Try to get caps via QMP qemuCaps=%p", qemuCaps); - /* - * We explicitly need to use -daemonize here, rather than - * virCommandDaemonize, because we need to synchronize - * with QEMU creating its monitor socket API. Using - * daemonize guarantees control won't return to libvirt - * until the socket is present. - */ - cmd = virCommandNewArgList(qemuCaps->binary, - "-S", - "-no-user-config", - "-nodefaults", - "-nographic", - "-M", "none", - "-qmp", monarg, - "-pidfile", pidfile, - "-daemonize", - NULL); - virCommandAddEnvPassCommon(cmd); - virCommandClearCaps(cmd); - virCommandSetGID(cmd, runGid); - virCommandSetUID(cmd, runUid); - - if (virCommandRun(cmd, &status) < 0) - goto cleanup; + cmd = virQEMUCapsInitQMPCommandNew(qemuCaps->binary, monarg, pidfile, + runUid, runGid); - if (status != 0) { - ret = 0; - VIR_DEBUG("QEMU %s exited with status %d", qemuCaps->binary, status); - goto cleanup; - } - - if (virPidFileReadPath(pidfile, &pid) < 0) { - VIR_DEBUG("Failed to read pidfile %s", pidfile); - ret = 0; - goto cleanup; - } - - memset(&vm, 0, sizeof(vm)); - vm.pid = pid; - - if (!(mon = qemuMonitorOpen(&vm, &config, true, &callbacks))) { - ret = 0; - goto cleanup; - } - - virObjectLock(mon); - - if (qemuMonitorSetCapabilities(mon) < 0) { - virErrorPtr err = virGetLastError(); - VIR_DEBUG("Failed to set monitor capabilities %s", - err ? err->message : "<unknown problem>"); - ret = 0; + if ((ret = virQEMUCapsInitQMPCommandRun(cmd, qemuCaps->binary, pidfile, + &config, &mon, &pid)) < 0) { + if (ret == -2) + ret = -1; + else + ret = 0; goto cleanup; } @@ -2617,28 +2682,11 @@ virQEMUCapsInitQMP(virQEMUCapsPtr qemuCaps, ret = 0; cleanup: - if (mon) - virObjectUnlock(mon); - qemuMonitorClose(mon); - virCommandAbort(cmd); - virCommandFree(cmd); + virQEMUCapsInitQMPCommandAbort(&cmd, &mon, &pid, pidfile); VIR_FREE(monarg); VIR_FREE(monpath); VIR_FREE(package); - - if (pid != 0) { - char ebuf[1024]; - - VIR_DEBUG("Killing QMP caps process %lld", (long long) pid); - if (virProcessKill(pid, SIGKILL) < 0 && errno != ESRCH) - VIR_ERROR(_("Failed to kill process %lld: %s"), - (long long) pid, - virStrerror(errno, ebuf, sizeof(ebuf))); - } - if (pidfile) { - unlink(pidfile); - VIR_FREE(pidfile); - } + VIR_FREE(pidfile); return ret; } -- 1.8.3.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list