---
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