Since libvirt switched to QMP capabilities probing recently, it starts
QEMU process used for this probing with -daemonize, which means
virCommandAbort can no longer reach these processes. As a result of
that, restarting libvirtd will leave several new QEMU processes behind.
Let's use QEMU's -pidfile and use it to kill the process when QMP caps
probing is done.
---
src/qemu/qemu_capabilities.c | 51 ++++++++++++++++++++++++++++++++++++++------
src/qemu/qemu_capabilities.h | 5 +++--
src/qemu/qemu_driver.c | 4 +++-
3 files changed, 51 insertions(+), 9 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 20b350a..bfefa92 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -29,6 +29,8 @@
#include "virterror_internal.h"
#include "util.h"
#include "virfile.h"
+#include "virpidfile.h"
+#include "virprocess.h"
#include "nodeinfo.h"
#include "cpu/cpu.h"
#include "domain_conf.h"
@@ -214,6 +216,7 @@ struct _qemuCapsCache {
virMutex lock;
virHashTablePtr binaries;
char *libDir;
+ char *runDir;
};
@@ -2180,7 +2183,8 @@ qemuCapsInitQMPBasic(qemuCapsPtr caps)
static int
qemuCapsInitQMP(qemuCapsPtr caps,
- const char *libDir)
+ const char *libDir,
+ const char *runDir)
{
int ret = -1;
virCommandPtr cmd = NULL;
@@ -2191,7 +2195,11 @@ qemuCapsInitQMP(qemuCapsPtr caps,
virDomainChrSourceDef config;
char *monarg = NULL;
char *monpath = NULL;
+ char *pidfile = NULL;
+ /* the ".sock" sufix is important to avoid a possible clash with a qemu
+ * domain called "capabilities"
+ */
if (virAsprintf(&monpath, "%s/%s", libDir,
"capabilities.monitor.sock") < 0) {
virReportOOMError();
goto cleanup;
@@ -2201,6 +2209,14 @@ qemuCapsInitQMP(qemuCapsPtr caps,
goto cleanup;
}
+ /* ".pidfile" suffix is used rather than ".pid" to avoid a
possible clash
+ * with a qemu domain called "capabilities"
+ */
+ if (virAsprintf(&pidfile, "%s/%s", runDir,
"capabilities.pidfile") < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
memset(&config, 0, sizeof(config));
config.type = VIR_DOMAIN_CHR_TYPE_UNIX;
config.data.nix.path = monpath;
@@ -2215,6 +2231,7 @@ qemuCapsInitQMP(qemuCapsPtr caps,
"-nographic",
"-M", "none",
"-qmp", monarg,
+ "-pidfile", pidfile,
"-daemonize",
NULL);
virCommandAddEnvPassCommon(cmd);
@@ -2300,12 +2317,32 @@ cleanup:
virCommandFree(cmd);
VIR_FREE(monarg);
VIR_FREE(monpath);
+
+ if (pidfile) {
+ char ebuf[1024];
+ pid_t pid;
+ int rc;
+
+ if ((rc = virPidFileReadPath(pidfile, &pid)) < 0) {
+ VIR_DEBUG("Failed to read pidfile %s: %d",
+ pidfile, virStrerror(-rc, ebuf, sizeof(ebuf)));
+ } else {
+ VIR_DEBUG("Killing QMP caps process %lld", (long long) pid);
+ if (virProcessKill(pid, SIGKILL) < 0)
+ VIR_DEBUG("Failed to kill process %lld: %s",
+ (long long) pid,
+ virStrerror(errno, ebuf, sizeof(ebuf)));
+ }
+ unlink(pidfile);
+ VIR_FREE(pidfile);
+ }
return ret;
}
qemuCapsPtr qemuCapsNewForBinary(const char *binary,
- const char *libDir)
+ const char *libDir,
+ const char *runDir)
{
qemuCapsPtr caps = qemuCapsNew();
struct stat sb;
@@ -2333,7 +2370,7 @@ qemuCapsPtr qemuCapsNewForBinary(const char *binary,
goto error;
}
- if ((rv = qemuCapsInitQMP(caps, libDir)) < 0)
+ if ((rv = qemuCapsInitQMP(caps, libDir, runDir)) < 0)
goto error;
if (!caps->usedQMP &&
@@ -2373,7 +2410,7 @@ qemuCapsHashDataFree(void *payload, const void *key
ATTRIBUTE_UNUSED)
qemuCapsCachePtr
-qemuCapsCacheNew(const char *libDir)
+qemuCapsCacheNew(const char *libDir, const char *runDir)
{
qemuCapsCachePtr cache;
@@ -2391,7 +2428,8 @@ qemuCapsCacheNew(const char *libDir)
if (!(cache->binaries = virHashCreate(10, qemuCapsHashDataFree)))
goto error;
- if (!(cache->libDir = strdup(libDir))) {
+ if (!(cache->libDir = strdup(libDir)) ||
+ !(cache->runDir = strdup(runDir))) {
virReportOOMError();
goto error;
}
@@ -2420,7 +2458,7 @@ qemuCapsCacheLookup(qemuCapsCachePtr cache, const char *binary)
if (!ret) {
VIR_DEBUG("Creating capabilities for %s",
binary);
- ret = qemuCapsNewForBinary(binary, cache->libDir);
+ ret = qemuCapsNewForBinary(binary, cache->libDir, cache->runDir);
if (ret) {
VIR_DEBUG("Caching capabilities %p for %s",
ret, binary);
@@ -2459,6 +2497,7 @@ qemuCapsCacheFree(qemuCapsCachePtr cache)
return;
VIR_FREE(cache->libDir);
+ VIR_FREE(cache->runDir);
virHashFree(cache->binaries);
virMutexDestroy(&cache->lock);
VIR_FREE(cache);
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 89f351c..5d343c1 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -163,7 +163,8 @@ typedef qemuCapsCache *qemuCapsCachePtr;
qemuCapsPtr qemuCapsNew(void);
qemuCapsPtr qemuCapsNewCopy(qemuCapsPtr caps);
qemuCapsPtr qemuCapsNewForBinary(const char *binary,
- const char *libDir);
+ const char *libDir,
+ const char *runDir);
int qemuCapsProbeQMP(qemuCapsPtr caps,
qemuMonitorPtr mon);
@@ -201,7 +202,7 @@ int qemuCapsGetMachineTypesCaps(qemuCapsPtr caps,
bool qemuCapsIsValid(qemuCapsPtr caps);
-qemuCapsCachePtr qemuCapsCacheNew(const char *libDir);
+qemuCapsCachePtr qemuCapsCacheNew(const char *libDir, const char *runDir);
qemuCapsPtr qemuCapsCacheLookup(qemuCapsCachePtr cache, const char *binary);
qemuCapsPtr qemuCapsCacheLookupCopy(qemuCapsCachePtr cache, const char *binary);
void qemuCapsCacheFree(qemuCapsCachePtr cache);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b0a0bb5..55d8027 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -767,7 +767,9 @@ qemudStartup(int privileged) {
if (qemuSecurityInit(qemu_driver) < 0)
goto error;
- if ((qemu_driver->capsCache = qemuCapsCacheNew(qemu_driver->libDir)) == NULL)
+ qemu_driver->capsCache = qemuCapsCacheNew(qemu_driver->libDir,
+ qemu_driver->stateDir);
+ if (!qemu_driver->capsCache)
goto error;
if ((qemu_driver->caps = qemuCreateCapabilities(qemu_driver)) == NULL)
--
1.7.12