[libvirt] [PATCH] qemu: monitor: fix unsafe monitor access

Peng Hao posted 1 patch 6 years, 1 month ago
Failed in applying to current master (apply log)
src/qemu/THREADS.txt             |  12 +-
src/qemu/qemu_block.c            |   5 +-
src/qemu/qemu_domain.c           |  64 +++++----
src/qemu/qemu_domain.h           |  12 +-
src/qemu/qemu_driver.c           | 258 ++++++++++++++++++++--------------
src/qemu/qemu_hotplug.c          | 296 ++++++++++++++++++++++-----------------
src/qemu/qemu_migration.c        | 104 ++++++++------
src/qemu/qemu_migration_cookie.c |   5 +-
src/qemu/qemu_process.c          | 108 ++++++++------
9 files changed, 507 insertions(+), 357 deletions(-)
mode change 100644 => 100755 src/qemu/THREADS.txt
mode change 100644 => 100755 src/qemu/qemu_block.c
mode change 100644 => 100755 src/qemu/qemu_domain.c
mode change 100644 => 100755 src/qemu/qemu_domain.h
mode change 100644 => 100755 src/qemu/qemu_driver.c
mode change 100644 => 100755 src/qemu/qemu_hotplug.c
mode change 100644 => 100755 src/qemu/qemu_migration.c
mode change 100644 => 100755 src/qemu/qemu_migration_cookie.c
mode change 100644 => 100755 src/qemu/qemu_process.c
[libvirt] [PATCH] qemu: monitor: fix unsafe monitor access
Posted by Peng Hao 6 years, 1 month ago
From: root <root@localhost.localdomain>

qemuDomainObjExitMonitor is unsafe

domain lock released when qemuDomainObjEnterMonitor finish,
So other thread (qemuProcessStop) has chance to modify priv->mon
to NULL. qemuDomainObjExitMonitor will never release the mon->lock,

that may cause problem:
thread get monitor ptr early, and then try to get mon->lock,
it will block forerver cause mon->lock not released by
qemuDomainObjExitMonitor.

Signed-off-by: Wang Yechao <wang.yechao255@zte.com.cn>
Signed-off-by: Peng Hao <peng.hao2@zte.com.cn>
---
 src/qemu/THREADS.txt             |  12 +-
 src/qemu/qemu_block.c            |   5 +-
 src/qemu/qemu_domain.c           |  64 +++++----
 src/qemu/qemu_domain.h           |  12 +-
 src/qemu/qemu_driver.c           | 258 ++++++++++++++++++++--------------
 src/qemu/qemu_hotplug.c          | 296 ++++++++++++++++++++++-----------------
 src/qemu/qemu_migration.c        | 104 ++++++++------
 src/qemu/qemu_migration_cookie.c |   5 +-
 src/qemu/qemu_process.c          | 108 ++++++++------
 9 files changed, 507 insertions(+), 357 deletions(-)
 mode change 100644 => 100755 src/qemu/THREADS.txt
 mode change 100644 => 100755 src/qemu/qemu_block.c
 mode change 100644 => 100755 src/qemu/qemu_domain.c
 mode change 100644 => 100755 src/qemu/qemu_domain.h
 mode change 100644 => 100755 src/qemu/qemu_driver.c
 mode change 100644 => 100755 src/qemu/qemu_hotplug.c
 mode change 100644 => 100755 src/qemu/qemu_migration.c
 mode change 100644 => 100755 src/qemu/qemu_migration_cookie.c
 mode change 100644 => 100755 src/qemu/qemu_process.c

diff --git a/src/qemu/THREADS.txt b/src/qemu/THREADS.txt
old mode 100644
new mode 100755
index 7243161..6a56003
--- a/src/qemu/THREADS.txt
+++ b/src/qemu/THREADS.txt
@@ -228,6 +228,7 @@ Design patterns
 
      virDomainObjPtr obj;
      qemuDomainObjPrivatePtr priv;
+     qemuMonitorPtr mon;
 
      obj = qemuDomObjFromDomain(dom);
 
@@ -236,9 +237,9 @@ Design patterns
      ...do prep work...
 
      if (virDomainObjIsActive(vm)) {
-         qemuDomainObjEnterMonitor(obj);
+         mon = qemuDomainObjEnterMonitor(obj);
          qemuMonitorXXXX(priv->mon);
-         qemuDomainObjExitMonitor(obj);
+         qemuDomainObjExitMonitor(obj, mon);
      }
 
      ...do final work...
@@ -251,6 +252,7 @@ Design patterns
 
      virDomainObjPtr obj;
      qemuDomainObjPrivatePtr priv;
+     qemuMonitorPtr mon;
 
      obj = qemuDomObjFromDomain(dom);
 
@@ -260,12 +262,12 @@ Design patterns
      ...do prep work...
 
      if (qemuDomainObjEnterMonitorAsync(driver, obj,
-                                        QEMU_ASYNC_JOB_TYPE) < 0) {
+                                        QEMU_ASYNC_JOB_TYPE, &mon) < 0) {
          /* domain died in the meantime */
          goto error;
      }
      ...start qemu job...
-     qemuDomainObjExitMonitor(driver, obj);
+     qemuDomainObjExitMonitor(driver, obj, mon);
 
      while (!finished) {
          if (qemuDomainObjEnterMonitorAsync(driver, obj,
@@ -274,7 +276,7 @@ Design patterns
              goto error;
          }
          ...monitor job progress...
-         qemuDomainObjExitMonitor(driver, obj);
+         qemuDomainObjExitMonitor(driver, obj, mon);
 
          virObjectUnlock(obj);
          sleep(aWhile);
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
old mode 100644
new mode 100755
index 585f025..d437802
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -327,17 +327,18 @@ qemuBlockNodeNamesDetect(virQEMUDriverPtr driver,
     virDomainDiskDefPtr disk;
     size_t i;
     int ret = -1;
+    qemuMonitorPtr mon;
 
     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QUERY_NAMED_BLOCK_NODES))
         return 0;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     data = qemuMonitorQueryNamedBlockNodes(qemuDomainGetMonitor(vm));
     blockstats = qemuMonitorQueryBlockstats(qemuDomainGetMonitor(vm));
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || !data || !blockstats)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || !data || !blockstats)
         goto cleanup;
 
     if (!(disktable = qemuBlockNodeNameGetBackingChain(data, blockstats)))
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
old mode 100644
new mode 100755
index aa65295..a09235e
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -5602,15 +5602,16 @@ qemuDomainObjEnterMonitorInternal(virQEMUDriverPtr driver,
 
 static void ATTRIBUTE_NONNULL(1)
 qemuDomainObjExitMonitorInternal(virQEMUDriverPtr driver,
-                                 virDomainObjPtr obj)
+                                 virDomainObjPtr obj,
+                                 qemuMonitorPtr mon)
 {
     qemuDomainObjPrivatePtr priv = obj->privateData;
     bool hasRefs;
 
-    hasRefs = virObjectUnref(priv->mon);
+    hasRefs = virObjectUnref(mon);
 
     if (hasRefs)
-        virObjectUnlock(priv->mon);
+        virObjectUnlock(mon);
 
     virObjectLock(obj);
     VIR_DEBUG("Exited monitor (mon=%p vm=%p name=%s)",
@@ -5624,11 +5625,13 @@ qemuDomainObjExitMonitorInternal(virQEMUDriverPtr driver,
         qemuDomainObjEndJob(driver, obj);
 }
 
-void qemuDomainObjEnterMonitor(virQEMUDriverPtr driver,
+qemuMonitorPtr qemuDomainObjEnterMonitor(virQEMUDriverPtr driver,
                                virDomainObjPtr obj)
 {
+    qemuMonitorPtr mon = qemuDomainGetMonitor(obj);
     ignore_value(qemuDomainObjEnterMonitorInternal(driver, obj,
                                                    QEMU_ASYNC_JOB_NONE));
+    return mon;
 }
 
 /* obj must NOT be locked before calling
@@ -5642,9 +5645,10 @@ void qemuDomainObjEnterMonitor(virQEMUDriverPtr driver,
  * from the live definition could no longer be valid.
  */
 int qemuDomainObjExitMonitor(virQEMUDriverPtr driver,
-                             virDomainObjPtr obj)
+                             virDomainObjPtr obj,
+                             qemuMonitorPtr mon)
 {
-    qemuDomainObjExitMonitorInternal(driver, obj);
+    qemuDomainObjExitMonitorInternal(driver, obj, mon);
     if (!virDomainObjIsActive(obj)) {
         if (!virGetLastError())
             virReportError(VIR_ERR_OPERATION_FAILED, "%s",
@@ -5671,8 +5675,10 @@ int qemuDomainObjExitMonitor(virQEMUDriverPtr driver,
 int
 qemuDomainObjEnterMonitorAsync(virQEMUDriverPtr driver,
                                virDomainObjPtr obj,
-                               qemuDomainAsyncJob asyncJob)
+                               qemuDomainAsyncJob asyncJob,
+                               qemuMonitorPtr *mon)
 {
+    *mon = qemuDomainGetMonitor(obj);
     return qemuDomainObjEnterMonitorInternal(driver, obj, asyncJob);
 }
 
@@ -6621,6 +6627,7 @@ qemuDomainSnapshotDiscard(virQEMUDriverPtr driver,
 {
     char *snapFile = NULL;
     int ret = -1;
+    qemuMonitorPtr mon;
     qemuDomainObjPrivatePtr priv;
     virDomainSnapshotObjPtr parentsnap = NULL;
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
@@ -6633,10 +6640,10 @@ qemuDomainSnapshotDiscard(virQEMUDriverPtr driver,
                 goto cleanup;
         } else {
             priv = vm->privateData;
-            qemuDomainObjEnterMonitor(driver, vm);
+            mon = qemuDomainObjEnterMonitor(driver, vm);
             /* we continue on even in the face of error */
             qemuMonitorDeleteSnapshot(priv->mon, snap->def->name);
-            ignore_value(qemuDomainObjExitMonitor(driver, vm));
+            ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
         }
     }
 
@@ -7477,14 +7484,15 @@ qemuDomainUpdateDeviceList(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     char **aliases;
     int rc;
+    qemuMonitorPtr mon;
 
     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_DEL_EVENT))
         return 0;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
     rc = qemuMonitorGetDeviceAliases(priv->mon, &aliases);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         return -1;
     if (rc < 0)
         return -1;
@@ -7504,16 +7512,17 @@ qemuDomainUpdateMemoryDeviceInfo(virQEMUDriverPtr driver,
     virHashTablePtr meminfo = NULL;
     int rc;
     size_t i;
+    qemuMonitorPtr mon;
 
     if (vm->def->nmems == 0)
         return 0;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     rc = qemuMonitorGetMemoryDeviceInfo(priv->mon, &meminfo);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0) {
         virHashFree(meminfo);
         return -1;
     }
@@ -8243,6 +8252,7 @@ qemuDomainUpdateCurrentMemorySize(virQEMUDriverPtr driver,
                                   virDomainObjPtr vm)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    qemuMonitorPtr mon;
     unsigned long long balloon;
     int ret = -1;
 
@@ -8275,9 +8285,9 @@ qemuDomainUpdateCurrentMemorySize(virQEMUDriverPtr driver,
             goto endjob;
         }
 
-        qemuDomainObjEnterMonitor(driver, vm);
+        mon = qemuDomainObjEnterMonitor(driver, vm);
         ret = qemuMonitorGetBalloonInfo(priv->mon, &balloon);
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             ret = -1;
 
  endjob:
@@ -8608,15 +8618,16 @@ qemuDomainRefreshVcpuInfo(virQEMUDriverPtr driver,
     bool hotplug;
     int rc;
     int ret = -1;
+    qemuMonitorPtr mon;
 
     hotplug = qemuDomainSupportsNewVcpuHotplug(vm);
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     rc = qemuMonitorGetCPUInfo(qemuDomainGetMonitor(vm), &info, maxvcpus, hotplug);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     if (rc < 0)
@@ -8721,6 +8732,7 @@ qemuDomainRefreshVcpuHalted(virQEMUDriverPtr driver,
     virBitmapPtr haltedmap = NULL;
     size_t i;
     int ret = -1;
+    qemuMonitorPtr mon;
 
     /* Not supported currently for TCG, see qemuDomainRefreshVcpuInfo */
     if (vm->def->virtType == VIR_DOMAIN_VIRT_QEMU)
@@ -8731,12 +8743,12 @@ qemuDomainRefreshVcpuHalted(virQEMUDriverPtr driver,
     if (!ARCH_IS_S390(vm->def->os.arch))
         return 0;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     haltedmap = qemuMonitorGetCpuHalted(qemuDomainGetMonitor(vm), maxvcpus);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || !haltedmap)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || !haltedmap)
         goto cleanup;
 
     for (i = 0; i < maxvcpus; i++) {
@@ -9081,13 +9093,14 @@ qemuDomainCheckMonitor(virQEMUDriverPtr driver,
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int ret;
+    qemuMonitorPtr mon;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     ret = qemuMonitorCheck(priv->mon);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         return -1;
 
     return ret;
@@ -11399,13 +11412,14 @@ qemuDomainCheckMigrationCapabilities(virQEMUDriverPtr driver,
     char **capStr;
     int ret = -1;
     int rc;
+    qemuMonitorPtr mon;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     rc = qemuMonitorGetMigrationCapabilities(priv->mon, &caps);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || rc < 0)
         goto cleanup;
 
     if (!caps) {
@@ -11429,14 +11443,14 @@ qemuDomainCheckMigrationCapabilities(virQEMUDriverPtr driver,
     }
 
     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_EVENT)) {
-        if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+        if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
             goto cleanup;
 
         rc = qemuMonitorSetMigrationCapability(priv->mon,
                                                QEMU_MONITOR_MIGRATION_CAPS_EVENTS,
                                                true);
 
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             goto cleanup;
 
         if (rc < 0) {
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
old mode 100644
new mode 100755
index f3ec5d8..ceee781
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -517,17 +517,19 @@ void qemuDomainObjReleaseAsyncJob(virDomainObjPtr obj);
 
 qemuMonitorPtr qemuDomainGetMonitor(virDomainObjPtr vm)
     ATTRIBUTE_NONNULL(1);
-void qemuDomainObjEnterMonitor(virQEMUDriverPtr driver,
+qemuMonitorPtr qemuDomainObjEnterMonitor(virQEMUDriverPtr driver,
                                virDomainObjPtr obj)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
 int qemuDomainObjExitMonitor(virQEMUDriverPtr driver,
-                             virDomainObjPtr obj)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
+                             virDomainObjPtr obj,
+                             qemuMonitorPtr mon)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
     ATTRIBUTE_RETURN_CHECK;
 int qemuDomainObjEnterMonitorAsync(virQEMUDriverPtr driver,
                                    virDomainObjPtr obj,
-                                   qemuDomainAsyncJob asyncJob)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+                                   qemuDomainAsyncJob asyncJob,
+                                   qemuMonitorPtr *mon)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
 
 
 qemuAgentPtr qemuDomainObjEnterAgent(virDomainObjPtr obj)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
old mode 100644
new mode 100755
index 8d77d89..ef84596
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1987,6 +1987,7 @@ static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
 {
     virQEMUDriverPtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
+    qemuMonitorPtr mon;
     int ret = -1;
     qemuDomainObjPrivatePtr priv;
     bool useAgent = false, agentRequested, acpiRequested;
@@ -2057,9 +2058,9 @@ static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
         }
 
         qemuDomainSetFakeReboot(driver, vm, isReboot);
-        qemuDomainObjEnterMonitor(driver, vm);
+        mon = qemuDomainObjEnterMonitor(driver, vm);
         ret = qemuMonitorSystemPowerdown(priv->mon);
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             ret = -1;
     }
 
@@ -2082,6 +2083,7 @@ qemuDomainReboot(virDomainPtr dom, unsigned int flags)
 {
     virQEMUDriverPtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
+    qemuMonitorPtr mon;
     int ret = -1;
     qemuDomainObjPrivatePtr priv;
     bool useAgent = false, agentRequested, acpiRequested;
@@ -2159,9 +2161,9 @@ qemuDomainReboot(virDomainPtr dom, unsigned int flags)
         }
 #endif
         qemuDomainSetFakeReboot(driver, vm, isReboot);
-        qemuDomainObjEnterMonitor(driver, vm);
+        mon = qemuDomainObjEnterMonitor(driver, vm);
         ret = qemuMonitorSystemPowerdown(priv->mon);
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             ret = -1;
     }
 
@@ -2179,6 +2181,7 @@ qemuDomainReset(virDomainPtr dom, unsigned int flags)
 {
     virQEMUDriverPtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
+    qemuMonitorPtr mon;
     int ret = -1;
     qemuDomainObjPrivatePtr priv;
     virDomainState state;
@@ -2201,9 +2204,9 @@ qemuDomainReset(virDomainPtr dom, unsigned int flags)
     }
 
     priv = vm->privateData;
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorSystemReset(priv->mon);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
     priv->fakeReboot = false;
@@ -2360,6 +2363,7 @@ static int qemuDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
     virDomainObjPtr vm;
     virDomainDefPtr def;
     virDomainDefPtr persistentDef;
+    qemuMonitorPtr mon;
     int ret = -1, r;
     virQEMUDriverConfigPtr cfg = NULL;
 
@@ -2438,9 +2442,9 @@ static int qemuDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
 
         if (def) {
             priv = vm->privateData;
-            qemuDomainObjEnterMonitor(driver, vm);
+            mon = qemuDomainObjEnterMonitor(driver, vm);
             r = qemuMonitorSetBalloon(priv->mon, newmem);
-            if (qemuDomainObjExitMonitor(driver, vm) < 0 || r < 0)
+            if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || r < 0)
                 goto endjob;
 
             /* Lack of balloon support is a fatal error */
@@ -2488,6 +2492,7 @@ static int qemuDomainSetMemoryStatsPeriod(virDomainPtr dom, int period,
     virDomainObjPtr vm;
     virDomainDefPtr def;
     virDomainDefPtr persistentDef;
+    qemuMonitorPtr mon;
     int ret = -1, r;
     virQEMUDriverConfigPtr cfg = NULL;
 
@@ -2520,9 +2525,9 @@ static int qemuDomainSetMemoryStatsPeriod(virDomainPtr dom, int period,
             goto endjob;
         }
 
-        qemuDomainObjEnterMonitor(driver, vm);
+        mon = qemuDomainObjEnterMonitor(driver, vm);
         r = qemuMonitorSetMemoryStatsPeriod(priv->mon, def->memballoon, period);
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             goto endjob;
         if (r < 0) {
             virReportError(VIR_ERR_OPERATION_INVALID, "%s",
@@ -2562,6 +2567,7 @@ static int qemuDomainInjectNMI(virDomainPtr domain, unsigned int flags)
 {
     virQEMUDriverPtr driver = domain->conn->privateData;
     virDomainObjPtr vm = NULL;
+    qemuMonitorPtr mon;
     int ret = -1;
     qemuDomainObjPrivatePtr priv;
 
@@ -2584,9 +2590,9 @@ static int qemuDomainInjectNMI(virDomainPtr domain, unsigned int flags)
         goto endjob;
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorInjectNMI(priv->mon);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
  endjob:
@@ -2608,6 +2614,7 @@ static int qemuDomainSendKey(virDomainPtr domain,
     virDomainObjPtr vm = NULL;
     int ret = -1;
     qemuDomainObjPrivatePtr priv;
+    qemuMonitorPtr mon;
 
     virCheckFlags(0, -1);
 
@@ -2647,9 +2654,9 @@ static int qemuDomainSendKey(virDomainPtr domain,
         goto endjob;
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorSendKey(priv->mon, holdtime, keycodes, nkeycodes);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
  endjob:
@@ -3806,6 +3813,7 @@ qemuDumpToFd(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     bool detach = false;
     int ret = -1;
+    qemuMonitorPtr mon;
 
     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DUMP_GUEST_MEMORY)) {
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
@@ -3825,7 +3833,7 @@ qemuDumpToFd(virQEMUDriverPtr driver,
         priv->job.dump_memory_only = true;
     }
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     if (dumpformat) {
@@ -3837,14 +3845,14 @@ qemuDumpToFd(virQEMUDriverPtr driver,
                              "for this QEMU binary"),
                            dumpformat);
             ret = -1;
-            ignore_value(qemuDomainObjExitMonitor(driver, vm));
+            ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
             goto cleanup;
         }
     }
 
     ret = qemuMonitorDumpToFd(priv->mon, fd, dumpformat, detach);
 
-    if ((qemuDomainObjExitMonitor(driver, vm) < 0) || ret < 0)
+    if ((qemuDomainObjExitMonitor(driver, vm, mon) < 0) || ret < 0)
         goto cleanup;
 
     if (detach)
@@ -3961,6 +3969,7 @@ qemuDomainCoreDumpWithFormat(virDomainPtr dom,
 {
     virQEMUDriverPtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
+    qemuMonitorPtr mon;
     qemuDomainObjPrivatePtr priv = NULL;
     bool resume = false, paused = false;
     int ret = -1;
@@ -4025,9 +4034,9 @@ qemuDomainCoreDumpWithFormat(virDomainPtr dom,
     } else if (((resume && paused) || (flags & VIR_DUMP_RESET)) &&
                virDomainObjIsActive(vm)) {
         if ((ret == 0) && (flags & VIR_DUMP_RESET)) {
-            qemuDomainObjEnterMonitor(driver, vm);
+            mon = qemuDomainObjEnterMonitor(driver, vm);
             ret = qemuMonitorSystemReset(priv->mon);
-            if (qemuDomainObjExitMonitor(driver, vm) < 0)
+            if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
                 ret = -1;
         }
 
@@ -4075,6 +4084,7 @@ qemuDomainScreenshot(virDomainPtr dom,
 {
     virQEMUDriverPtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
+    qemuMonitorPtr mon;
     qemuDomainObjPrivatePtr priv;
     char *tmp = NULL;
     int tmp_fd = -1;
@@ -4122,12 +4132,12 @@ qemuDomainScreenshot(virDomainPtr dom,
 
     qemuSecuritySetSavedStateLabel(driver->securityManager, vm->def, tmp);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorScreendump(priv->mon, tmp) < 0) {
-        ignore_value(qemuDomainObjExitMonitor(driver, vm));
+        ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
         goto endjob;
     }
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto endjob;
 
     if (VIR_CLOSE(tmp_fd) < 0) {
@@ -4603,6 +4613,7 @@ processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virDomainDeviceDef dev;
     virDomainNetDefPtr def;
+    qemuMonitorPtr mon;
     virNetDevRxFilterPtr guestFilter = NULL;
     virNetDevRxFilterPtr hostFilter = NULL;
     int ret;
@@ -4648,9 +4659,9 @@ processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
     VIR_DEBUG("process NIC_RX_FILTER_CHANGED event for network "
               "device %s in domain %s", def->info.alias, vm->def->name);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorQueryRxFilter(priv->mon, devAlias, &guestFilter);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
     if (ret < 0)
         goto endjob;
@@ -5552,6 +5563,7 @@ qemuDomainGetIOThreadsLive(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv;
     qemuMonitorIOThreadInfoPtr *iothreads = NULL;
     virDomainIOThreadInfoPtr *info_ret = NULL;
+    qemuMonitorPtr mon;
     int niothreads = 0;
     size_t i;
     int ret = -1;
@@ -5572,9 +5584,9 @@ qemuDomainGetIOThreadsLive(virQEMUDriverPtr driver,
         goto endjob;
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     niothreads = qemuMonitorGetIOThreads(priv->mon, &iothreads);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto endjob;
     if (niothreads < 0)
         goto endjob;
@@ -5872,11 +5884,12 @@ qemuDomainHotplugAddIOThread(virQEMUDriverPtr driver,
     int new_niothreads = 0;
     qemuMonitorIOThreadInfoPtr *new_iothreads = NULL;
     virDomainIOThreadIDDefPtr iothrid;
+    qemuMonitorPtr mon;
 
     if (virAsprintf(&alias, "iothread%u", iothread_id) < 0)
         return -1;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     rc = qemuMonitorAddObject(priv->mon, "iothread", alias, NULL);
     exp_niothreads++;
@@ -5891,7 +5904,7 @@ qemuDomainHotplugAddIOThread(virQEMUDriverPtr driver,
                                                   &new_iothreads)) < 0)
         goto exit_monitor;
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     if (new_niothreads != exp_niothreads) {
@@ -5940,7 +5953,7 @@ qemuDomainHotplugAddIOThread(virQEMUDriverPtr driver,
     return ret;
 
  exit_monitor:
-    ignore_value(qemuDomainObjExitMonitor(driver, vm));
+    ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
     goto cleanup;
 }
 
@@ -5958,11 +5971,12 @@ qemuDomainHotplugDelIOThread(virQEMUDriverPtr driver,
     unsigned int exp_niothreads = vm->def->niothreadids;
     int new_niothreads = 0;
     qemuMonitorIOThreadInfoPtr *new_iothreads = NULL;
+    qemuMonitorPtr mon;
 
     if (virAsprintf(&alias, "iothread%u", iothread_id) < 0)
         return -1;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     rc = qemuMonitorDelObject(priv->mon, alias);
     exp_niothreads--;
@@ -5973,7 +5987,7 @@ qemuDomainHotplugDelIOThread(virQEMUDriverPtr driver,
                                                   &new_iothreads)) < 0)
         goto exit_monitor;
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     if (new_niothreads != exp_niothreads) {
@@ -6004,7 +6018,7 @@ qemuDomainHotplugDelIOThread(virQEMUDriverPtr driver,
     return ret;
 
  exit_monitor:
-    ignore_value(qemuDomainObjExitMonitor(driver, vm));
+    ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
     goto cleanup;
 }
 
@@ -10826,6 +10840,7 @@ qemuDomainBlockResize(virDomainPtr dom,
     int ret = -1;
     char *device = NULL;
     virDomainDiskDefPtr disk = NULL;
+    qemuMonitorPtr mon;
 
     virCheckFlags(VIR_DOMAIN_BLOCK_RESIZE_BYTES, -1);
 
@@ -10879,12 +10894,12 @@ qemuDomainBlockResize(virDomainPtr dom,
     if (!(device = qemuAliasFromDisk(disk)))
         goto endjob;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorBlockResize(priv->mon, device, size) < 0) {
-        ignore_value(qemuDomainObjExitMonitor(driver, vm));
+        ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
         goto endjob;
     }
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto endjob;
 
     ret = 0;
@@ -10945,6 +10960,7 @@ qemuDomainBlocksStatsGather(virQEMUDriverPtr driver,
     virDomainDiskDefPtr disk;
     virHashTablePtr blockstats = NULL;
     qemuBlockStatsPtr stats;
+    qemuMonitorPtr mon;
     int nstats;
     char *diskAlias = NULL;
     int ret = -1;
@@ -10965,9 +10981,9 @@ qemuDomainBlocksStatsGather(virQEMUDriverPtr driver,
             goto cleanup;
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     nstats = qemuMonitorGetAllBlockStatsInfo(priv->mon, &blockstats, false);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || nstats < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || nstats < 0)
         goto cleanup;
 
     if (VIR_ALLOC(*retstats) < 0)
@@ -11499,6 +11515,7 @@ qemuDomainMemoryStatsInternal(virQEMUDriverPtr driver,
 {
     int ret = -1;
     long rss;
+    qemuMonitorPtr mon;
 
     if (!virDomainObjIsActive(vm)) {
         virReportError(VIR_ERR_OPERATION_INVALID,
@@ -11508,10 +11525,10 @@ qemuDomainMemoryStatsInternal(virQEMUDriverPtr driver,
 
     if (vm->def->memballoon &&
         vm->def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO) {
-        qemuDomainObjEnterMonitor(driver, vm);
+        mon = qemuDomainObjEnterMonitor(driver, vm);
         ret = qemuMonitorGetMemoryStats(qemuDomainGetMonitor(vm),
                                         vm->def->memballoon, stats, nr_stats);
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             ret = -1;
 
         if (ret < 0 || ret >= nr_stats)
@@ -11634,6 +11651,7 @@ qemuDomainMemoryPeek(virDomainPtr dom,
     int fd = -1, ret = -1;
     qemuDomainObjPrivatePtr priv;
     virQEMUDriverConfigPtr cfg = NULL;
+    qemuMonitorPtr mon;
 
     virCheckFlags(VIR_MEMORY_VIRTUAL | VIR_MEMORY_PHYSICAL, -1);
 
@@ -11673,19 +11691,19 @@ qemuDomainMemoryPeek(virDomainPtr dom,
     qemuSecuritySetSavedStateLabel(driver->securityManager, vm->def, tmp);
 
     priv = vm->privateData;
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     if (flags == VIR_MEMORY_VIRTUAL) {
         if (qemuMonitorSaveVirtualMemory(priv->mon, offset, size, tmp) < 0) {
-            ignore_value(qemuDomainObjExitMonitor(driver, vm));
+            ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
             goto endjob;
         }
     } else {
         if (qemuMonitorSavePhysicalMemory(priv->mon, offset, size, tmp) < 0) {
-            ignore_value(qemuDomainObjExitMonitor(driver, vm));
+            ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
             goto endjob;
         }
     }
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto endjob;
 
     /* Read the memory file into buffer. */
@@ -11898,6 +11916,7 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
     virHashTablePtr stats = NULL;
     qemuBlockStats *entry;
     char *alias = NULL;
+    qemuMonitorPtr mon;
 
     virCheckFlags(0, -1);
 
@@ -11945,14 +11964,14 @@ qemuDomainGetBlockInfo(virDomainPtr dom,
         goto endjob;
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     rc = qemuMonitorGetAllBlockStatsInfo(qemuDomainGetMonitor(vm),
                                          &stats, false);
     if (rc >= 0)
         rc = qemuMonitorBlockStatsUpdateCapacity(qemuDomainGetMonitor(vm),
                                                  stats, false);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || rc < 0)
         goto endjob;
 
     if (!(entry = virHashLookup(stats, alias))) {
@@ -13239,13 +13258,14 @@ qemuDomainGetJobInfoDumpStats(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     qemuMonitorDumpStats stats = { 0 };
     int rc;
+    qemuMonitorPtr mon;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_NONE, &mon) < 0)
         return -1;
 
     rc = qemuMonitorQueryDump(priv->mon, &stats);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || rc < 0)
         return -1;
 
     jobInfo->stats.dump = stats;
@@ -13431,6 +13451,7 @@ static int qemuDomainAbortJob(virDomainPtr dom)
     virDomainObjPtr vm;
     int ret = -1;
     qemuDomainObjPrivatePtr priv;
+    qemuMonitorPtr mon;
     int reason;
 
     if (!(vm = qemuDomObjFromDomain(dom)))
@@ -13474,9 +13495,9 @@ static int qemuDomainAbortJob(virDomainPtr dom)
 
     VIR_DEBUG("Cancelling job at client request");
     qemuDomainObjAbortAsyncJob(vm);
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorMigrateCancel(priv->mon);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
  endjob:
@@ -13496,6 +13517,7 @@ qemuDomainMigrateSetMaxDowntime(virDomainPtr dom,
     virQEMUDriverPtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
     qemuDomainObjPrivatePtr priv;
+    qemuMonitorPtr mon;
     int ret = -1;
 
     virCheckFlags(0, -1);
@@ -13518,9 +13540,9 @@ qemuDomainMigrateSetMaxDowntime(virDomainPtr dom,
     priv = vm->privateData;
 
     VIR_DEBUG("Setting migration downtime to %llums", downtime);
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorSetMigrationDowntime(priv->mon, downtime);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
  endjob:
@@ -13540,6 +13562,7 @@ qemuDomainMigrateGetMaxDowntime(virDomainPtr dom,
     virQEMUDriverPtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
     qemuDomainObjPrivatePtr priv;
+    qemuMonitorPtr mon;
     qemuMonitorMigrationParams migparams = { 0 };
     int ret = -1;
 
@@ -13561,7 +13584,7 @@ qemuDomainMigrateGetMaxDowntime(virDomainPtr dom,
     }
 
     priv = vm->privateData;
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     if (qemuMonitorGetMigrationParams(priv->mon, &migparams) == 0) {
         if (migparams.downtimeLimit_set) {
@@ -13574,7 +13597,7 @@ qemuDomainMigrateGetMaxDowntime(virDomainPtr dom,
         }
     }
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
  endjob:
@@ -13594,6 +13617,7 @@ qemuDomainMigrateGetCompressionCache(virDomainPtr dom,
     virQEMUDriverPtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
     qemuDomainObjPrivatePtr priv;
+    qemuMonitorPtr mon;
     int ret = -1;
 
     virCheckFlags(0, -1);
@@ -13622,11 +13646,11 @@ qemuDomainMigrateGetCompressionCache(virDomainPtr dom,
         goto endjob;
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     ret = qemuMonitorGetMigrationCacheSize(priv->mon, cacheSize);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
  endjob:
@@ -13645,6 +13669,7 @@ qemuDomainMigrateSetCompressionCache(virDomainPtr dom,
     virQEMUDriverPtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
     qemuDomainObjPrivatePtr priv;
+    qemuMonitorPtr mon;
     int ret = -1;
 
     virCheckFlags(0, -1);
@@ -13673,12 +13698,12 @@ qemuDomainMigrateSetCompressionCache(virDomainPtr dom,
         goto endjob;
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     VIR_DEBUG("Setting compression cache to %llu B", cacheSize);
     ret = qemuMonitorSetMigrationCacheSize(priv->mon, cacheSize);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
  endjob:
@@ -13697,6 +13722,7 @@ qemuDomainMigrateSetMaxSpeed(virDomainPtr dom,
     virQEMUDriverPtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
     qemuDomainObjPrivatePtr priv;
+    qemuMonitorPtr mon;
     int ret = -1;
 
     virCheckFlags(0, -1);
@@ -13727,9 +13753,9 @@ qemuDomainMigrateSetMaxSpeed(virDomainPtr dom,
         }
 
         VIR_DEBUG("Setting migration bandwidth to %luMbs", bandwidth);
-        qemuDomainObjEnterMonitor(driver, vm);
+        mon = qemuDomainObjEnterMonitor(driver, vm);
         ret = qemuMonitorSetMigrationSpeed(priv->mon, bandwidth);
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             ret = -1;
 
         if (ret == 0)
@@ -13782,6 +13808,7 @@ qemuDomainMigrateStartPostCopy(virDomainPtr dom,
     virQEMUDriverPtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
     qemuDomainObjPrivatePtr priv;
+    qemuMonitorPtr mon;
     int ret = -1;
 
     virCheckFlags(0, -1);
@@ -13818,9 +13845,9 @@ qemuDomainMigrateStartPostCopy(virDomainPtr dom,
     }
 
     VIR_DEBUG("Starting post-copy");
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorMigrateStartPostCopy(priv->mon);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
  endjob:
@@ -14018,6 +14045,7 @@ qemuDomainSnapshotCreateActiveInternal(virConnectPtr conn,
     virObjectEventPtr event = NULL;
     bool resume = false;
     int ret = -1;
+    qemuMonitorPtr mon;
 
     if (!qemuMigrationIsAllowed(driver, vm, false, 0))
         goto cleanup;
@@ -14040,13 +14068,13 @@ qemuDomainSnapshotCreateActiveInternal(virConnectPtr conn,
     }
 
     if (qemuDomainObjEnterMonitorAsync(driver, vm,
-                                       QEMU_ASYNC_JOB_SNAPSHOT) < 0) {
+                                       QEMU_ASYNC_JOB_SNAPSHOT, &mon) < 0) {
         resume = false;
         goto cleanup;
     }
 
     ret = qemuMonitorCreateSnapshot(priv->mon, snap->def->name);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
     if (ret < 0)
         goto cleanup;
@@ -14696,6 +14724,7 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
     char *source = NULL;
     const char *formatStr = NULL;
     int ret = -1, rc;
+    qemuMonitorPtr mon;
 
     if (!(device = qemuAliasFromDisk(dd->disk)))
         goto cleanup;
@@ -14728,13 +14757,13 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
      * Otherwise the following monitor command only constructs the command.
      */
     if (!actions &&
-        qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+        qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         goto cleanup;
 
     ret = rc = qemuMonitorDiskSnapshot(priv->mon, actions, device, source,
                                        formatStr, reuse);
     if (!actions) {
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             ret = -1;
     }
 
@@ -14765,6 +14794,7 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
     virQEMUDriverConfigPtr cfg = NULL;
     qemuDomainSnapshotDiskDataPtr diskdata = NULL;
     virErrorPtr orig_err = NULL;
+    qemuMonitorPtr mon;
 
     if (!virDomainObjIsActive(vm)) {
         virReportError(VIR_ERR_OPERATION_INVALID,
@@ -14812,12 +14842,12 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
     }
 
     if (actions && do_transaction) {
-        if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+        if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
             goto cleanup;
 
         ret = qemuMonitorTransaction(priv->mon, actions);
 
-        if (qemuDomainObjExitMonitor(driver, vm) < 0 || ret < 0) {
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || ret < 0) {
             ret = -1;
             goto error;
         }
@@ -15755,6 +15785,7 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
     bool was_stopped = false;
     qemuDomainSaveCookiePtr cookie;
     virCPUDefPtr origCPU = NULL;
+    qemuMonitorPtr mon;
 
     virCheckFlags(VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING |
                   VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED |
@@ -15942,10 +15973,10 @@ qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
             }
 
             if (qemuDomainObjEnterMonitorAsync(driver, vm,
-                                               QEMU_ASYNC_JOB_START) < 0)
+                                               QEMU_ASYNC_JOB_START, &mon) < 0)
                 goto endjob;
             rc = qemuMonitorLoadSnapshot(priv->mon, snap->def->name);
-            if (qemuDomainObjExitMonitor(driver, vm) < 0)
+            if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
                 goto endjob;
             if (rc < 0) {
                 /* XXX resume domain if it was running before the
@@ -16307,6 +16338,7 @@ static int qemuDomainQemuMonitorCommand(virDomainPtr domain, const char *cmd,
     virDomainObjPtr vm = NULL;
     int ret = -1;
     qemuDomainObjPrivatePtr priv;
+    qemuMonitorPtr mon;
     bool hmp;
 
     virCheckFlags(VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP, -1);
@@ -16332,9 +16364,9 @@ static int qemuDomainQemuMonitorCommand(virDomainPtr domain, const char *cmd,
 
     hmp = !!(flags & VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorArbitraryCommand(priv->mon, cmd, result, hmp);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
  endjob:
@@ -16608,6 +16640,7 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
     qemuMonitorBlockJobInfo info;
     virStorageSourcePtr oldsrc = NULL;
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+    qemuMonitorPtr mon;
 
     if (!disk->mirror) {
         virReportError(VIR_ERR_OPERATION_INVALID,
@@ -16618,9 +16651,9 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
 
     /* Probe the status, if needed.  */
     if (!disk->mirrorState) {
-        qemuDomainObjEnterMonitor(driver, vm);
+        mon = qemuDomainObjEnterMonitor(driver, vm);
         rc = qemuMonitorGetBlockJobInfo(priv->mon, disk->info.alias, &info);
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             goto cleanup;
         if (rc < 0)
             goto cleanup;
@@ -16687,9 +16720,9 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
      * that pivot failed, we need to reflect that failure into the
      * overall return value.  */
     disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_PIVOT;
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorDrivePivot(priv->mon, device);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0) {
         ret = -1;
         goto cleanup;
     }
@@ -16729,6 +16762,7 @@ qemuDomainBlockPullCommon(virQEMUDriverPtr driver,
     char *backingPath = NULL;
     unsigned long long speed = bandwidth;
     int ret = -1;
+    qemuMonitorPtr mon;
 
     if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE && !base) {
         virReportError(VIR_ERR_INVALID_ARG, "%s",
@@ -16797,14 +16831,14 @@ qemuDomainBlockPullCommon(virQEMUDriverPtr driver,
         speed <<= 20;
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     if (baseSource)
         basePath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src,
                                              baseSource);
     if (!baseSource || basePath)
         ret = qemuMonitorBlockStream(priv->mon, device, basePath, backingPath,
                                      speed);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
     if (ret < 0)
@@ -16843,6 +16877,7 @@ qemuDomainBlockJobAbort(virDomainPtr dom,
     bool async = !!(flags & VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC);
     virDomainObjPtr vm;
     int ret = -1;
+    qemuMonitorPtr mon;
 
     virCheckFlags(VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC |
                   VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT, -1);
@@ -16891,9 +16926,9 @@ qemuDomainBlockJobAbort(virDomainPtr dom,
             save = true;
         }
 
-        qemuDomainObjEnterMonitor(driver, vm);
+        mon = qemuDomainObjEnterMonitor(driver, vm);
         ret = qemuMonitorBlockJobCancel(qemuDomainGetMonitor(vm), device);
-        if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0) {
             ret = -1;
             goto endjob;
         }
@@ -16994,6 +17029,7 @@ qemuDomainGetBlockJobInfo(virDomainPtr dom,
     virDomainDiskDefPtr disk;
     int ret = -1;
     qemuMonitorBlockJobInfo rawInfo;
+    qemuMonitorPtr mon;
 
     virCheckFlags(VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES, -1);
 
@@ -17022,10 +17058,10 @@ qemuDomainGetBlockJobInfo(virDomainPtr dom,
         goto endjob;
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorGetBlockJobInfo(qemuDomainGetMonitor(vm),
                                      disk->info.alias, &rawInfo);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
     if (ret <= 0)
         goto endjob;
@@ -17071,6 +17107,7 @@ qemuDomainBlockJobSetSpeed(virDomainPtr dom,
     virDomainObjPtr vm;
     const char *device;
     unsigned long long speed = bandwidth;
+    qemuMonitorPtr mon;
 
     virCheckFlags(VIR_DOMAIN_BLOCK_JOB_SPEED_BANDWIDTH_BYTES, -1);
 
@@ -17109,11 +17146,11 @@ qemuDomainBlockJobSetSpeed(virDomainPtr dom,
     if (!(device = qemuAliasFromDisk(disk)))
         goto endjob;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorBlockJobSetSpeed(qemuDomainGetMonitor(vm),
                                       device,
                                       speed);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
  endjob:
@@ -17206,6 +17243,7 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm,
     const char *format = NULL;
     virErrorPtr monitor_error = NULL;
     bool reuse = !!(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT);
+    qemuMonitorPtr mon;
 
     /* Preliminaries: find the disk we are editing, sanity checks */
     virCheckFlags(VIR_DOMAIN_BLOCK_COPY_SHALLOW |
@@ -17325,13 +17363,13 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm,
     }
 
     /* Actually start the mirroring */
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     /* qemuMonitorDriveMirror needs to honor the REUSE_EXT flag as specified
      * by the user regardless of how @reuse was modified */
     ret = qemuMonitorDriveMirror(priv->mon, device, mirror->path, format,
                                  bandwidth, granularity, buf_size, flags);
     virDomainAuditDisk(vm, NULL, mirror, "mirror", ret >= 0);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
     if (ret < 0) {
         monitor_error = virSaveLastError();
@@ -17565,6 +17603,7 @@ qemuDomainBlockCommit(virDomainPtr dom,
     char *backingPath = NULL;
     virStorageSourcePtr mirror = NULL;
     unsigned long long speed = bandwidth;
+    qemuMonitorPtr mon;
 
     /* XXX Add support for COMMIT_DELETE */
     virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW |
@@ -17728,7 +17767,7 @@ qemuDomainBlockCommit(virDomainPtr dom,
         disk->mirror = mirror;
         disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT;
     }
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     basePath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src,
                                          baseSource);
     topPath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src,
@@ -17737,7 +17776,7 @@ qemuDomainBlockCommit(virDomainPtr dom,
         ret = qemuMonitorBlockCommit(priv->mon, device,
                                      topPath, basePath, backingPath,
                                      speed);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0) {
         ret = -1;
         goto endjob;
     }
@@ -17790,6 +17829,7 @@ qemuDomainOpenGraphics(virDomainPtr dom,
     virDomainObjPtr vm = NULL;
     int ret = -1;
     qemuDomainObjPrivatePtr priv;
+    qemuMonitorPtr mon;
     const char *protocol;
 
     virCheckFlags(VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH, -1);
@@ -17833,10 +17873,10 @@ qemuDomainOpenGraphics(virDomainPtr dom,
     if (qemuSecuritySetImageFDLabel(driver->securityManager, vm->def, fd) < 0)
         goto endjob;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorOpenGraphics(priv->mon, protocol, fd, "graphicsfd",
                                   (flags & VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH) != 0);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
  endjob:
@@ -17856,6 +17896,7 @@ qemuDomainOpenGraphicsFD(virDomainPtr dom,
     virDomainObjPtr vm = NULL;
     int ret = -1;
     qemuDomainObjPrivatePtr priv;
+    qemuMonitorPtr mon;
     const char *protocol;
     int pair[2] = {-1, -1};
 
@@ -17905,10 +17946,10 @@ qemuDomainOpenGraphicsFD(virDomainPtr dom,
 
     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
         goto cleanup;
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorOpenGraphics(priv->mon, protocol, pair[1], "graphicsfd",
                                   (flags & VIR_DOMAIN_OPEN_GRAPHICS_SKIPAUTH));
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
     qemuDomainObjEndJob(driver, vm);
     if (ret < 0)
@@ -18023,6 +18064,7 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
     virTypedParameterPtr eventParams = NULL;
     int eventNparams = 0;
     int eventMaxparams = 0;
+    qemuMonitorPtr mon;
 
     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                   VIR_DOMAIN_AFFECT_CONFIG, -1);
@@ -18287,12 +18329,12 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
          /* NB: Let's let QEMU decide how to handle issues with _length
           * via the JSON error code from the block_set_io_throttle call */
 
-        qemuDomainObjEnterMonitor(driver, vm);
+        mon = qemuDomainObjEnterMonitor(driver, vm);
         ret = qemuMonitorSetBlockIoThrottle(priv->mon, device,
                                             &info, supportMaxOptions,
                                             set_fields & QEMU_BLOCK_IOTUNE_SET_GROUP_NAME,
                                             supportMaxLengthOptions);
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             ret = -1;
         if (ret < 0)
             goto endjob;
@@ -18360,6 +18402,7 @@ qemuDomainGetBlockIoTune(virDomainPtr dom,
     virDomainDefPtr def = NULL;
     virDomainDefPtr persistentDef = NULL;
     virDomainBlockIoTuneInfo reply = {0};
+    qemuMonitorPtr mon;
     char *device = NULL;
     int ret = -1;
     int maxparams;
@@ -18423,9 +18466,9 @@ qemuDomainGetBlockIoTune(virDomainPtr dom,
 
         if (!(device = qemuAliasFromDisk(disk)))
             goto endjob;
-        qemuDomainObjEnterMonitor(driver, vm);
+        mon = qemuDomainObjEnterMonitor(driver, vm);
         ret = qemuMonitorGetBlockIoThrottle(priv->mon, device, &reply);
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             goto endjob;
         if (ret < 0)
             goto endjob;
@@ -18514,6 +18557,7 @@ qemuDomainGetDiskErrors(virDomainPtr dom,
     virDomainObjPtr vm = NULL;
     qemuDomainObjPrivatePtr priv;
     virHashTablePtr table = NULL;
+    qemuMonitorPtr mon;
     int ret = -1;
     size_t i;
     int n = 0;
@@ -18542,9 +18586,9 @@ qemuDomainGetDiskErrors(virDomainPtr dom,
         goto endjob;
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     table = qemuMonitorGetBlockInfo(priv->mon);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto endjob;
     if (!table)
         goto endjob;
@@ -18799,6 +18843,7 @@ qemuDomainPMWakeup(virDomainPtr dom,
     virDomainObjPtr vm;
     int ret = -1;
     qemuDomainObjPrivatePtr priv;
+    qemuMonitorPtr mon;
 
     virCheckFlags(0, -1);
 
@@ -18826,9 +18871,9 @@ qemuDomainPMWakeup(virDomainPtr dom,
        goto endjob;
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorSystemWakeup(priv->mon);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
  endjob:
@@ -19206,6 +19251,7 @@ qemuDomainSetTime(virDomainPtr dom,
     qemuDomainObjPrivatePtr priv;
     virDomainObjPtr vm;
     qemuAgentPtr agent;
+    qemuMonitorPtr mon;
     bool rtcSync = flags & VIR_DOMAIN_TIME_SYNC;
     int ret = -1;
     int rv;
@@ -19259,9 +19305,9 @@ qemuDomainSetTime(virDomainPtr dom,
 
     /* Don't try to call rtc-reset-reinjection if it's not available */
     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_RTC_RESET_REINJECTION)) {
-        qemuDomainObjEnterMonitor(driver, vm);
+        mon = qemuDomainObjEnterMonitor(driver, vm);
         rv = qemuMonitorRTCResetReinjection(priv->mon);
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             goto endjob;
 
         if (rv < 0)
@@ -20062,6 +20108,7 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
     virHashTablePtr stats = NULL;
     virHashTablePtr nodestats = NULL;
     virJSONValuePtr nodedata = NULL;
+    qemuMonitorPtr mon;
     qemuDomainObjPrivatePtr priv = dom->privateData;
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
     bool fetchnodedata = virQEMUCapsGet(priv->qemuCaps,
@@ -20071,7 +20118,7 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
     bool visitBacking = !!(privflags & QEMU_DOMAIN_STATS_BACKING);
 
     if (HAVE_JOB(privflags) && virDomainObjIsActive(dom)) {
-        qemuDomainObjEnterMonitor(driver, dom);
+        mon = qemuDomainObjEnterMonitor(driver, dom);
         rc = qemuMonitorGetAllBlockStatsInfo(priv->mon, &stats,
                                              visitBacking);
         if (rc >= 0)
@@ -20081,7 +20128,7 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
         if (fetchnodedata)
             nodedata = qemuMonitorQueryNamedBlockNodes(priv->mon);
 
-        if (qemuDomainObjExitMonitor(driver, dom) < 0)
+        if (qemuDomainObjExitMonitor(driver, dom, mon) < 0)
             goto cleanup;
 
         /* failure to retrieve stats is fine at this point */
@@ -21096,6 +21143,7 @@ qemuDomainSetBlockThreshold(virDomainPtr dom,
     qemuDomainObjPrivatePtr priv;
     virDomainObjPtr vm = NULL;
     virStorageSourcePtr src;
+    qemuMonitorPtr mon;
     char *nodename = NULL;
     int rc;
     int ret = -1;
@@ -21142,9 +21190,9 @@ qemuDomainSetBlockThreshold(virDomainPtr dom,
     if (VIR_STRDUP(nodename, src->nodestorage) < 0)
         goto endjob;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     rc = qemuMonitorSetBlockThreshold(priv->mon, nodename, threshold);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || rc < 0)
         goto endjob;
 
     ret = 0;
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
old mode 100644
new mode 100755
index 53bfe47..6f436e0
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -203,6 +203,7 @@ qemuHotplugWaitForTrayEject(virQEMUDriverPtr driver,
 {
     unsigned long long now;
     int rc;
+    qemuMonitorPtr mon;
 
     if (virTimeMillisNow(&now) < 0)
         return -1;
@@ -223,9 +224,9 @@ qemuHotplugWaitForTrayEject(virQEMUDriverPtr driver,
     }
 
     /* re-issue ejection command to pop out the media */
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     rc = qemuMonitorEjectMedia(qemuDomainGetMonitor(vm), driveAlias, false);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || rc < 0)
         return -1;
 
     return 0;
@@ -260,6 +261,7 @@ qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
     qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
     qemuDomainStorageSourcePrivatePtr srcPriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(disk->src);
     qemuDomainSecretInfoPtr secinfo = NULL;
+    qemuMonitorPtr mon;
     const char *format = NULL;
     char *sourcestr = NULL;
 
@@ -286,9 +288,9 @@ qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
     if (!(driveAlias = qemuAliasFromDisk(disk)))
         goto error;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     rc = qemuMonitorEjectMedia(priv->mon, driveAlias, force);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     /* If the tray is present and tray change event is supported wait for it to open. */
@@ -315,12 +317,12 @@ qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
                     format = virStorageFileFormatTypeToString(disk->src->format);
             }
         }
-        qemuDomainObjEnterMonitor(driver, vm);
+        mon = qemuDomainObjEnterMonitor(driver, vm);
         rc = qemuMonitorChangeMedia(priv->mon,
                                     driveAlias,
                                     sourcestr,
                                     format);
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             goto cleanup;
     }
 
@@ -377,6 +379,7 @@ qemuDomainAttachDiskGeneric(virConnectPtr conn,
     qemuDomainStorageSourcePrivatePtr srcPriv;
     qemuDomainSecretInfoPtr secinfo = NULL;
     qemuDomainSecretInfoPtr encinfo = NULL;
+    qemuMonitorPtr mon;
 
     if (qemuHotplugPrepareDiskAccess(driver, vm, disk, NULL, false) < 0)
         goto cleanup;
@@ -418,7 +421,7 @@ qemuDomainAttachDiskGeneric(virConnectPtr conn,
     if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0)
         goto error;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     if (secobjProps) {
         rv = qemuMonitorAddObject(priv->mon, "secret", secinfo->s.aes.alias,
@@ -445,7 +448,7 @@ qemuDomainAttachDiskGeneric(virConnectPtr conn,
     if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
         goto exit_monitor;
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0) {
         ret = -2;
         goto error;
     }
@@ -475,7 +478,7 @@ qemuDomainAttachDiskGeneric(virConnectPtr conn,
         ignore_value(qemuMonitorDelObject(priv->mon, secinfo->s.aes.alias));
     if (encobjAdded)
         ignore_value(qemuMonitorDelObject(priv->mon, encinfo->s.aes.alias));
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -2;
     virErrorRestore(&orig_err);
 
@@ -523,6 +526,7 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver,
     virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_CONTROLLER,
                                { .controller = controller } };
     bool releaseaddr = false;
+    qemuMonitorPtr mon;
 
     if (controller->type != VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
@@ -561,9 +565,9 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver,
     if (VIR_REALLOC_N(vm->def->controllers, vm->def->ncontrollers+1) < 0)
         goto cleanup;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorAddDevice(priv->mon, devstr);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0) {
         releaseaddr = false;
         ret = -1;
         goto cleanup;
@@ -846,6 +850,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
     bool charDevPlugged = false;
     bool netdevPlugged = false;
     bool hostPlugged = false;
+    qemuMonitorPtr mon;
 
     /* preallocate new slot for device */
     if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0)
@@ -1081,11 +1086,11 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
             goto cleanup;
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
         if (qemuMonitorAttachCharDev(priv->mon, charDevAlias, net->data.vhostuser) < 0) {
-            ignore_value(qemuDomainObjExitMonitor(driver, vm));
+            ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
             virDomainAuditNet(vm, NULL, net, "attach", false);
             goto cleanup;
         }
@@ -1096,7 +1101,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
         if (qemuMonitorAddNetdev(priv->mon, netstr,
                                  tapfd, tapfdName, tapfdSize,
                                  vhostfd, vhostfdName, vhostfdSize) < 0) {
-            ignore_value(qemuDomainObjExitMonitor(driver, vm));
+            ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
             virDomainAuditNet(vm, NULL, net, "attach", false);
             goto try_remove;
         }
@@ -1105,14 +1110,14 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
         if (qemuMonitorAddHostNetwork(priv->mon, netstr,
                                       tapfd, tapfdName, tapfdSize,
                                       vhostfd, vhostfdName, vhostfdSize) < 0) {
-            ignore_value(qemuDomainObjExitMonitor(driver, vm));
+            ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
             virDomainAuditNet(vm, NULL, net, "attach", false);
             goto try_remove;
         }
         hostPlugged = true;
     }
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     for (i = 0; i < tapfdSize; i++)
@@ -1124,13 +1129,13 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
                                       queueSize, priv->qemuCaps)))
         goto try_remove;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorAddDevice(priv->mon, nicstr) < 0) {
-        ignore_value(qemuDomainObjExitMonitor(driver, vm));
+        ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
         virDomainAuditNet(vm, NULL, net, "attach", false);
         goto try_remove;
     }
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     /* set link state */
@@ -1139,11 +1144,11 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
             virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                            _("device alias not found: cannot set link state to down"));
         } else {
-            qemuDomainObjEnterMonitor(driver, vm);
+            mon = qemuDomainObjEnterMonitor(driver, vm);
 
             if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NETDEV)) {
                 if (qemuMonitorSetLink(priv->mon, net->info.alias, VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN) < 0) {
-                    ignore_value(qemuDomainObjExitMonitor(driver, vm));
+                    ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
                     virDomainAuditNet(vm, NULL, net, "attach", false);
                     goto try_remove;
                 }
@@ -1152,7 +1157,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
                                _("setting of link state not supported: Link is up"));
             }
 
-            if (qemuDomainObjExitMonitor(driver, vm) < 0)
+            if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
                 goto cleanup;
         }
         /* link set to down */
@@ -1220,7 +1225,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
         if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NETDEV)) {
             char *netdev_name;
             if (virAsprintf(&netdev_name, "host%s", net->info.alias) >= 0) {
-                qemuDomainObjEnterMonitor(driver, vm);
+                mon = qemuDomainObjEnterMonitor(driver, vm);
                 if (charDevPlugged &&
                     qemuMonitorDetachCharDev(priv->mon, charDevAlias) < 0)
                     VIR_WARN("Failed to remove associated chardev %s", charDevAlias);
@@ -1228,7 +1233,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
                     qemuMonitorRemoveNetdev(priv->mon, netdev_name) < 0)
                     VIR_WARN("Failed to remove network backend for netdev %s",
                              netdev_name);
-                ignore_value(qemuDomainObjExitMonitor(driver, vm));
+                ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
                 VIR_FREE(netdev_name);
             }
         } else {
@@ -1237,12 +1242,12 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
     } else {
         char *hostnet_name;
         if (virAsprintf(&hostnet_name, "host%s", net->info.alias) >= 0) {
-            qemuDomainObjEnterMonitor(driver, vm);
+            mon = qemuDomainObjEnterMonitor(driver, vm);
             if (hostPlugged &&
                 qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0)
                 VIR_WARN("Failed to remove network backend for vlan %d, net %s",
                          vlan, hostnet_name);
-            ignore_value(qemuDomainObjExitMonitor(driver, vm));
+            ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
             VIR_FREE(hostnet_name);
         }
     }
@@ -1271,6 +1276,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver,
     int backend;
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
     unsigned int flags = 0;
+    qemuMonitorPtr mon;
 
     if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0)
         goto cleanup;
@@ -1363,10 +1369,10 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver,
                                              configfd_name, priv->qemuCaps)))
         goto error;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorAddDeviceWithFd(priv->mon, devstr,
                                      configfd, configfd_name);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto error;
 
     virDomainAuditHostdev(vm, hostdev, "attach", ret == 0);
@@ -1416,13 +1422,14 @@ qemuDomainDelTLSObjects(virQEMUDriverPtr driver,
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virErrorPtr orig_err;
+    qemuMonitorPtr mon;
 
     if (!tlsAlias && !secAlias)
         return;
 
     virErrorPreserveLast(&orig_err);
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         goto cleanup;
 
     if (tlsAlias)
@@ -1431,7 +1438,7 @@ qemuDomainDelTLSObjects(virQEMUDriverPtr driver,
     if (secAlias)
         ignore_value(qemuMonitorDelObject(priv->mon, secAlias));
 
-    ignore_value(qemuDomainObjExitMonitor(driver, vm));
+    ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
 
  cleanup:
     virErrorRestore(&orig_err);
@@ -1450,11 +1457,12 @@ qemuDomainAddTLSObjects(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int rc;
     virErrorPtr orig_err;
+    qemuMonitorPtr mon;
 
     if (!tlsAlias && !secAlias)
         return 0;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     if (secAlias) {
@@ -1473,11 +1481,11 @@ qemuDomainAddTLSObjects(virQEMUDriverPtr driver,
             goto error;
     }
 
-    return qemuDomainObjExitMonitor(driver, vm);
+    return qemuDomainObjExitMonitor(driver, vm, mon);
 
  error:
     virErrorPreserveLast(&orig_err);
-    ignore_value(qemuDomainObjExitMonitor(driver, vm));
+    ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
     virErrorRestore(&orig_err);
     qemuDomainDelTLSObjects(driver, vm, asyncJob, secAlias, tlsAlias);
 
@@ -1588,6 +1596,7 @@ qemuDomainDelChardevTLSObjects(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     char *tlsAlias = NULL;
     char *secAlias = NULL;
+    qemuMonitorPtr mon;
 
     if (dev->type != VIR_DOMAIN_CHR_TYPE_TCP ||
         dev->data.tcp.haveTLS != VIR_TRISTATE_BOOL_YES) {
@@ -1606,13 +1615,13 @@ qemuDomainDelChardevTLSObjects(virQEMUDriverPtr driver,
         !(secAlias = qemuDomainGetSecretAESAlias(inAlias, false)))
         goto cleanup;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     ignore_value(qemuMonitorDelObject(priv->mon, tlsAlias));
     if (secAlias)
         ignore_value(qemuMonitorDelObject(priv->mon, secAlias));
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     ret = 0;
@@ -1640,6 +1649,7 @@ int qemuDomainAttachRedirdevDevice(virConnectPtr conn,
     char *secAlias = NULL;
     bool need_release = false;
     virErrorPtr orig_err;
+    qemuMonitorPtr mon;
 
     if (qemuAssignDeviceRedirdevAlias(def, redirdev, -1) < 0)
         goto cleanup;
@@ -1662,7 +1672,7 @@ int qemuDomainAttachRedirdevDevice(virConnectPtr conn,
                                        &tlsAlias, &secAlias) < 0)
         goto audit;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     if (qemuMonitorAttachCharDev(priv->mon,
                                  charAlias,
@@ -1673,7 +1683,7 @@ int qemuDomainAttachRedirdevDevice(virConnectPtr conn,
     if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
         goto exit_monitor;
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto audit;
 
     def->redirdevs[def->nredirdevs++] = redirdev;
@@ -1694,7 +1704,7 @@ int qemuDomainAttachRedirdevDevice(virConnectPtr conn,
     /* detach associated chardev on error */
     if (chardevAdded)
         ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias));
-    ignore_value(qemuDomainObjExitMonitor(driver, vm));
+    ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
     virErrorRestore(&orig_err);
     qemuDomainDelTLSObjects(driver, vm, QEMU_ASYNC_JOB_NONE,
                             secAlias, tlsAlias);
@@ -1882,6 +1892,7 @@ int qemuDomainAttachChrDevice(virConnectPtr conn,
     char *tlsAlias = NULL;
     char *secAlias = NULL;
     bool need_release = false;
+    qemuMonitorPtr mon;
 
     if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
         qemuDomainPrepareChannel(chr, priv->channelTargetDir) < 0)
@@ -1921,7 +1932,7 @@ int qemuDomainAttachChrDevice(virConnectPtr conn,
                                        &tlsAlias, &secAlias) < 0)
         goto audit;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     if (qemuMonitorAttachCharDev(priv->mon, charAlias, chr->source) < 0)
         goto exit_monitor;
@@ -1930,7 +1941,7 @@ int qemuDomainAttachChrDevice(virConnectPtr conn,
     if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
         goto exit_monitor;
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto audit;
 
     qemuDomainChrInsertPreAlloced(vmdef, chr);
@@ -1961,7 +1972,7 @@ int qemuDomainAttachChrDevice(virConnectPtr conn,
     /* detach associated chardev on error */
     if (chardevAttached)
         qemuMonitorDetachCharDev(priv->mon, charAlias);
-    ignore_value(qemuDomainObjExitMonitor(driver, vm));
+    ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
     virErrorRestore(&orig_err);
 
     qemuDomainDelTLSObjects(driver, vm, QEMU_ASYNC_JOB_NONE,
@@ -1993,6 +2004,7 @@ qemuDomainAttachRNGDevice(virConnectPtr conn,
     const char *type;
     int ret = -1;
     int rv;
+    qemuMonitorPtr mon;
 
     if (qemuAssignDeviceRNGAlias(vm->def, rng) < 0)
         goto cleanup;
@@ -2033,7 +2045,7 @@ qemuDomainAttachRNGDevice(virConnectPtr conn,
             goto audit;
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD &&
         qemuMonitorAttachCharDev(priv->mon, charAlias,
@@ -2050,7 +2062,7 @@ qemuDomainAttachRNGDevice(virConnectPtr conn,
     if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
         goto exit_monitor;
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0) {
         releaseaddr = false;
         goto cleanup;
     }
@@ -2085,7 +2097,7 @@ qemuDomainAttachRNGDevice(virConnectPtr conn,
         ignore_value(qemuMonitorDelObject(priv->mon, objAlias));
     if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD && chardevAdded)
         ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias));
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         releaseaddr = false;
     virErrorRestore(&orig_err);
 
@@ -2127,6 +2139,7 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
     int id;
     int ret = -1;
     int rv;
+    qemuMonitorPtr mon;
 
     qemuDomainMemoryDeviceAlignSize(vm->def, mem);
 
@@ -2172,7 +2185,7 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
     if (qemuDomainAdjustMaxMemLock(vm) < 0)
         goto removedef;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     rv = qemuMonitorAddObject(priv->mon, backendType, objalias, props);
     props = NULL; /* qemuMonitorAddObject consumes */
     if (rv < 0)
@@ -2182,7 +2195,7 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
     if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
         goto exit_monitor;
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0) {
         /* we shouldn't touch mem now, as the def might be freed */
         mem = NULL;
         goto audit;
@@ -2227,7 +2240,7 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
     virErrorPreserveLast(&orig_err);
     if (objAdded)
         ignore_value(qemuMonitorDelObject(priv->mon, objalias));
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         mem = NULL;
     virErrorRestore(&orig_err);
     if (!mem)
@@ -2261,6 +2274,7 @@ qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver,
     bool teardownlabel = false;
     bool teardowndevice = false;
     int ret = -1;
+    qemuMonitorPtr mon;
 
     if (priv->usbaddrs) {
         if (virDomainUSBAddressEnsure(priv->usbaddrs, hostdev->info) < 0)
@@ -2293,9 +2307,9 @@ qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver,
     if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0)
         goto cleanup;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorAddDevice(priv->mon, devstr);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0) {
         ret = -1;
         goto cleanup;
     }
@@ -2348,6 +2362,7 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn,
     virJSONValuePtr secobjProps = NULL;
     virDomainHostdevSubsysSCSIPtr scsisrc = &hostdev->source.subsys.u.scsi;
     qemuDomainSecretInfoPtr secinfo = NULL;
+    qemuMonitorPtr mon;
 
     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_SCSI_GENERIC)) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
@@ -2411,7 +2426,7 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn,
     if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0)
         goto cleanup;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     if (secobjProps) {
         rv = qemuMonitorAddObject(priv->mon, "secret", secinfo->s.aes.alias,
@@ -2429,7 +2444,7 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn,
     if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
         goto exit_monitor;
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     virDomainAuditHostdev(vm, hostdev, "attach", true);
@@ -2466,7 +2481,7 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn,
     }
     if (secobjAdded)
         ignore_value(qemuMonitorDelObject(priv->mon, secinfo->s.aes.alias));
-    ignore_value(qemuDomainObjExitMonitor(driver, vm));
+    ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
     virErrorRestore(&orig_err);
 
     virDomainAuditHostdev(vm, hostdev, "attach", false);
@@ -2491,6 +2506,7 @@ qemuDomainAttachSCSIVHostDevice(virQEMUDriverPtr driver,
     bool teardownlabel = false;
     bool teardowndevice = false;
     bool releaseaddr = false;
+    qemuMonitorPtr mon;
 
     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_SCSI_GENERIC)) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
@@ -2550,11 +2566,11 @@ qemuDomainAttachSCSIVHostDevice(virQEMUDriverPtr driver,
     if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0)
         goto cleanup;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     ret = qemuMonitorAddDeviceWithFd(priv->mon, devstr, vhostfd, vhostfdName);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || ret < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || ret < 0)
         goto audit;
 
     vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
@@ -2652,6 +2668,7 @@ qemuDomainAttachShmemDevice(virQEMUDriverPtr driver,
     virJSONValuePtr props = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_SHMEM, { .shmem = shmem } };
+    qemuMonitorPtr mon;
 
     switch ((virDomainShmemModel)shmem->model) {
     case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_PLAIN:
@@ -2695,7 +2712,7 @@ qemuDomainAttachShmemDevice(virQEMUDriverPtr driver,
             goto cleanup;
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     if (shmem->server.enabled) {
         if (qemuMonitorAttachCharDev(priv->mon, charAlias,
@@ -2715,7 +2732,7 @@ qemuDomainAttachShmemDevice(virQEMUDriverPtr driver,
     if (qemuMonitorAddDevice(priv->mon, shmstr) < 0)
         goto exit_monitor;
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0) {
         release_address = false;
         goto cleanup;
     }
@@ -2750,7 +2767,7 @@ qemuDomainAttachShmemDevice(virQEMUDriverPtr driver,
             ignore_value(qemuMonitorDelObject(priv->mon, memAlias));
     }
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         release_address = false;
 
     virErrorRestore(&orig_err);
@@ -2772,6 +2789,7 @@ qemuDomainAttachWatchdog(virQEMUDriverPtr driver,
     char *watchdogstr = NULL;
     bool releaseAddress = false;
     int rv;
+    qemuMonitorPtr mon;
 
     if (vm->def->watchdog) {
         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
@@ -2804,14 +2822,14 @@ qemuDomainAttachWatchdog(virQEMUDriverPtr driver,
 
     actionStr = virDomainWatchdogActionTypeToString(actualAction);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     rv = qemuMonitorSetWatchdogAction(priv->mon, actionStr);
 
     if (rv >= 0)
         rv = qemuMonitorAddDevice(priv->mon, watchdogstr);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0) {
         releaseAddress = false;
         goto cleanup;
     }
@@ -2846,6 +2864,7 @@ qemuDomainAttachInputDevice(virQEMUDriverPtr driver,
     bool teardowndevice = false;
     bool teardownlabel = false;
     bool teardowncgroup = false;
+    qemuMonitorPtr mon;
 
     if (input->bus != VIR_DOMAIN_INPUT_BUS_USB &&
         input->bus != VIR_DOMAIN_INPUT_BUS_VIRTIO) {
@@ -2887,11 +2906,11 @@ qemuDomainAttachInputDevice(virQEMUDriverPtr driver,
     if (VIR_REALLOC_N(vm->def->inputs, vm->def->ninputs + 1) < 0)
         goto cleanup;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
         goto exit_monitor;
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0) {
         releaseaddr = false;
         goto cleanup;
     }
@@ -2921,7 +2940,7 @@ qemuDomainAttachInputDevice(virQEMUDriverPtr driver,
     return ret;
 
  exit_monitor:
-    if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0) {
         releaseaddr = false;
         goto cleanup;
     }
@@ -3026,6 +3045,7 @@ int qemuDomainChangeNetLinkState(virQEMUDriverPtr driver,
 {
     int ret = -1;
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    qemuMonitorPtr mon;
 
     if (!dev->info.alias) {
         virReportError(VIR_ERR_OPERATION_FAILED, "%s",
@@ -3035,7 +3055,7 @@ int qemuDomainChangeNetLinkState(virQEMUDriverPtr driver,
 
     VIR_DEBUG("dev: %s, state: %d", dev->info.alias, linkstate);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     ret = qemuMonitorSetLink(priv->mon, dev->info.alias, linkstate);
     if (ret < 0)
@@ -3045,7 +3065,7 @@ int qemuDomainChangeNetLinkState(virQEMUDriverPtr driver,
     dev->linkstate = linkstate;
 
  cleanup:
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         return -1;
 
     return ret;
@@ -3733,6 +3753,7 @@ qemuDomainRemoveDiskDevice(virQEMUDriverPtr driver,
     char *drivestr;
     char *objAlias = NULL;
     char *encAlias = NULL;
+    qemuMonitorPtr mon;
 
     VIR_DEBUG("Removing disk %s from domain %p %s",
               disk->info.alias, vm, vm->def->name);
@@ -3770,7 +3791,7 @@ qemuDomainRemoveDiskDevice(virQEMUDriverPtr driver,
         }
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     qemuMonitorDriveDel(priv->mon, drivestr);
     VIR_FREE(drivestr);
@@ -3788,7 +3809,7 @@ qemuDomainRemoveDiskDevice(virQEMUDriverPtr driver,
     if (disk->src->haveTLS)
         ignore_value(qemuMonitorDelObject(priv->mon, disk->src->tlsAlias));
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         return -1;
 
     virDomainAuditDisk(vm, disk->src, NULL, "detach", true);
@@ -3867,6 +3888,7 @@ qemuDomainRemoveMemoryDevice(virQEMUDriverPtr driver,
     char *backendAlias = NULL;
     int rc;
     int idx;
+    qemuMonitorPtr mon;
 
     VIR_DEBUG("Removing memory device %s from domain %p %s",
               mem->info.alias, vm, vm->def->name);
@@ -3874,9 +3896,9 @@ qemuDomainRemoveMemoryDevice(virQEMUDriverPtr driver,
     if (virAsprintf(&backendAlias, "mem%s", mem->info.alias) < 0)
         return -1;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     rc = qemuMonitorDelObject(priv->mon, backendAlias);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         rc = -1;
 
     VIR_FREE(backendAlias);
@@ -3963,6 +3985,7 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver,
     char *drivealias = NULL;
     char *objAlias = NULL;
     bool is_vfio = false;
+    qemuMonitorPtr mon;
 
     VIR_DEBUG("Removing host device %s from domain %p %s",
               hostdev->info->alias, vm, vm->def->name);
@@ -3989,14 +4012,14 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver,
                 goto cleanup;
         }
 
-        qemuDomainObjEnterMonitor(driver, vm);
+        mon = qemuDomainObjEnterMonitor(driver, vm);
         qemuMonitorDriveDel(priv->mon, drivealias);
 
         /* If it fails, then so be it - it was a best shot */
         if (objAlias)
             ignore_value(qemuMonitorDelObject(priv->mon, objAlias));
 
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             goto cleanup;
     }
 
@@ -4086,6 +4109,7 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
     size_t i;
     int ret = -1;
     int actualType = virDomainNetGetActualType(net);
+    qemuMonitorPtr mon;
 
     if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
         /* this function handles all hostdev and netdev cleanup */
@@ -4102,10 +4126,10 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
         goto cleanup;
 
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NETDEV)) {
         if (qemuMonitorRemoveNetdev(priv->mon, hostnet_name) < 0) {
-            if (qemuDomainObjExitMonitor(driver, vm) < 0)
+            if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
                 goto cleanup;
             virDomainAuditNet(vm, net, NULL, "detach", false);
             goto cleanup;
@@ -4118,7 +4142,7 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
                 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                                _("unable to determine original VLAN"));
             }
-            if (qemuDomainObjExitMonitor(driver, vm) < 0)
+            if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
                 goto cleanup;
             virDomainAuditNet(vm, net, NULL, "detach", false);
             goto cleanup;
@@ -4135,7 +4159,7 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
         }
     }
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     virDomainAuditNet(vm, net, NULL, "detach", true);
@@ -4192,6 +4216,7 @@ qemuDomainRemoveChrDevice(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int ret = -1;
     int rc;
+    qemuMonitorPtr mon;
 
     VIR_DEBUG("Removing character device %s from domain %p %s",
               chr->info.alias, vm, vm->def->name);
@@ -4199,10 +4224,10 @@ qemuDomainRemoveChrDevice(virQEMUDriverPtr driver,
     if (!(charAlias = qemuAliasChardevFromDevAlias(chr->info.alias)))
         goto cleanup;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     rc = qemuMonitorDetachCharDev(priv->mon, charAlias);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     if (rc == 0 &&
@@ -4248,6 +4273,7 @@ qemuDomainRemoveRNGDevice(virQEMUDriverPtr driver,
     ssize_t idx;
     int ret = -1;
     int rc;
+    qemuMonitorPtr mon;
 
     VIR_DEBUG("Removing RNG device %s from domain %p %s",
               rng->info.alias, vm, vm->def->name);
@@ -4259,11 +4285,11 @@ qemuDomainRemoveRNGDevice(virQEMUDriverPtr driver,
     if (!(charAlias = qemuAliasChardevFromDevAlias(rng->info.alias)))
         goto cleanup;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     rc = qemuMonitorDelObject(priv->mon, objAlias);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD &&
@@ -4311,6 +4337,7 @@ qemuDomainRemoveShmemDevice(virQEMUDriverPtr driver,
     char *memAlias = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virObjectEventPtr event = NULL;
+    qemuMonitorPtr mon;
 
     VIR_DEBUG("Removing shmem device %s from domain %p %s",
               shmem->info.alias, vm, vm->def->name);
@@ -4323,14 +4350,14 @@ qemuDomainRemoveShmemDevice(virQEMUDriverPtr driver,
             return -1;
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     if (shmem->server.enabled)
         rc = qemuMonitorDetachCharDev(priv->mon, charAlias);
     else
         rc = qemuMonitorDelObject(priv->mon, memAlias);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     virDomainAuditShmem(vm, shmem, "detach", rc == 0);
@@ -4418,6 +4445,7 @@ qemuDomainRemoveRedirdevDevice(virQEMUDriverPtr driver,
     char *charAlias = NULL;
     ssize_t idx;
     int ret = -1;
+    qemuMonitorPtr mon;
 
     VIR_DEBUG("Removing redirdev device %s from domain %p %s",
               dev->info.alias, vm, vm->def->name);
@@ -4425,13 +4453,13 @@ qemuDomainRemoveRedirdevDevice(virQEMUDriverPtr driver,
     if (!(charAlias = qemuAliasChardevFromDevAlias(dev->info.alias)))
         goto cleanup;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     /* DeviceDel from Detach may remove chardev,
      * so we cannot rely on return status to delete TLS chardevs.
      */
     ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias));
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     if (qemuDomainDelChardevTLSObjects(driver, vm, dev->source, charAlias) < 0)
@@ -4629,6 +4657,7 @@ qemuDomainDetachVirtioDiskDevice(virQEMUDriverPtr driver,
 {
     int ret = -1;
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    qemuMonitorPtr mon;
 
     if (qemuIsMultiFunctionDevice(vm->def, &detach->info)) {
         virReportError(VIR_ERR_OPERATION_FAILED,
@@ -4644,14 +4673,14 @@ qemuDomainDetachVirtioDiskDevice(virQEMUDriverPtr driver,
 
     qemuDomainMarkDeviceForRemoval(vm, &detach->info);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             goto cleanup;
         virDomainAuditDisk(vm, detach->src, NULL, "detach", false);
         goto cleanup;
     }
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
@@ -4669,20 +4698,21 @@ qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
 {
     int ret = -1;
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    qemuMonitorPtr mon;
 
     if (qemuDomainDiskBlockJobIsActive(detach))
         goto cleanup;
 
     qemuDomainMarkDeviceForRemoval(vm, &detach->info);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             goto cleanup;
         virDomainAuditDisk(vm, detach->src, NULL, "detach", false);
         goto cleanup;
     }
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
@@ -4812,6 +4842,7 @@ int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver,
     int idx, ret = -1;
     virDomainControllerDefPtr detach = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    qemuMonitorPtr mon;
 
     if ((idx = virDomainControllerFind(vm->def,
                                        dev->data.controller->type,
@@ -4861,12 +4892,12 @@ int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver,
 
     qemuDomainMarkDeviceForRemoval(vm, &detach->info);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorDelDevice(priv->mon, detach->info.alias)) {
-        ignore_value(qemuDomainObjExitMonitor(driver, vm));
+        ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
         goto cleanup;
     }
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
@@ -4885,6 +4916,7 @@ qemuDomainDetachHostPCIDevice(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virDomainHostdevSubsysPCIPtr pcisrc = &detach->source.subsys.u.pci;
     int ret;
+    qemuMonitorPtr mon;
 
     if (qemuIsMultiFunctionDevice(vm->def, detach->info)) {
         virReportError(VIR_ERR_OPERATION_FAILED,
@@ -4896,9 +4928,9 @@ qemuDomainDetachHostPCIDevice(virQEMUDriverPtr driver,
 
     qemuDomainMarkDeviceForRemoval(vm, detach->info);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorDelDevice(priv->mon, detach->info->alias);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
     return ret;
@@ -4911,6 +4943,7 @@ qemuDomainDetachHostUSBDevice(virQEMUDriverPtr driver,
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int ret;
+    qemuMonitorPtr mon;
 
     if (!detach->info->alias) {
         virReportError(VIR_ERR_OPERATION_FAILED,
@@ -4920,9 +4953,9 @@ qemuDomainDetachHostUSBDevice(virQEMUDriverPtr driver,
 
     qemuDomainMarkDeviceForRemoval(vm, detach->info);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorDelDevice(priv->mon, detach->info->alias);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
     return ret;
@@ -4935,6 +4968,7 @@ qemuDomainDetachHostSCSIDevice(virQEMUDriverPtr driver,
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int ret = -1;
+    qemuMonitorPtr mon;
 
     if (!detach->info->alias) {
         virReportError(VIR_ERR_OPERATION_FAILED,
@@ -4944,10 +4978,10 @@ qemuDomainDetachHostSCSIDevice(virQEMUDriverPtr driver,
 
     qemuDomainMarkDeviceForRemoval(vm, detach->info);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorDelDevice(priv->mon, detach->info->alias);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         return -1;
 
     return ret;
@@ -4960,6 +4994,7 @@ qemuDomainDetachSCSIVHostDevice(virQEMUDriverPtr driver,
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int ret = -1;
+    qemuMonitorPtr mon;
 
     if (!detach->info->alias) {
         virReportError(VIR_ERR_OPERATION_FAILED,
@@ -4969,10 +5004,10 @@ qemuDomainDetachSCSIVHostDevice(virQEMUDriverPtr driver,
 
     qemuDomainMarkDeviceForRemoval(vm, detach->info);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorDelDevice(priv->mon, detach->info->alias);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         return -1;
 
     return ret;
@@ -5107,6 +5142,7 @@ qemuDomainDetachShmemDevice(virQEMUDriverPtr driver,
     ssize_t idx = -1;
     virDomainShmemDefPtr shmem = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    qemuMonitorPtr mon;
 
     if ((idx = virDomainShmemDefFind(vm->def, dev)) < 0) {
         virReportError(VIR_ERR_DEVICE_MISSING,
@@ -5133,11 +5169,11 @@ qemuDomainDetachShmemDevice(virQEMUDriverPtr driver,
     }
 
     qemuDomainMarkDeviceForRemoval(vm, &shmem->info);
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     ret = qemuMonitorDelDevice(priv->mon, shmem->info.alias);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
     if (ret == 0) {
@@ -5160,6 +5196,7 @@ qemuDomainDetachWatchdog(virQEMUDriverPtr driver,
     int ret = -1;
     virDomainWatchdogDefPtr watchdog = vm->def->watchdog;
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    qemuMonitorPtr mon;
 
     /* While domains can have up to one watchdog, the one supplied by the user
      * doesn't necessarily match the one domain has. Refuse to detach in such
@@ -5183,11 +5220,11 @@ qemuDomainDetachWatchdog(virQEMUDriverPtr driver,
     }
 
     qemuDomainMarkDeviceForRemoval(vm, &watchdog->info);
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     ret = qemuMonitorDelDevice(priv->mon, watchdog->info.alias);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
     if (ret == 0) {
@@ -5211,6 +5248,7 @@ qemuDomainDetachRedirdevDevice(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virDomainRedirdevDefPtr tmpRedirdevDef;
     ssize_t idx;
+    qemuMonitorPtr mon;
 
     if ((idx = virDomainRedirdevDefFind(vm->def, dev)) < 0) {
         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
@@ -5228,12 +5266,12 @@ qemuDomainDetachRedirdevDevice(virQEMUDriverPtr driver,
 
     qemuDomainMarkDeviceForRemoval(vm, &tmpRedirdevDef->info);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorDelDevice(priv->mon, tmpRedirdevDef->info.alias) < 0) {
-        ignore_value(qemuDomainObjExitMonitor(driver, vm));
+        ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
         goto cleanup;
     }
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
@@ -5253,6 +5291,7 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver,
     int detachidx, ret = -1;
     virDomainNetDefPtr detach = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    qemuMonitorPtr mon;
 
     if ((detachidx = virDomainNetFindIdx(vm->def, dev->data.net)) < 0)
         goto cleanup;
@@ -5291,14 +5330,14 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver,
 
     qemuDomainMarkDeviceForRemoval(vm, &detach->info);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             goto cleanup;
         virDomainAuditNet(vm, detach, NULL, "detach", false);
         goto cleanup;
     }
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
@@ -5325,6 +5364,7 @@ qemuDomainChangeGraphicsPasswords(virQEMUDriverPtr driver,
     const char *password;
     int ret = -1;
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+    qemuMonitorPtr mon;
 
     if (!auth->passwd && !defaultPasswd) {
         ret = 0;
@@ -5335,7 +5375,7 @@ qemuDomainChangeGraphicsPasswords(virQEMUDriverPtr driver,
     if (auth->connected)
         connected = virDomainGraphicsAuthConnectedTypeToString(auth->connected);
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         goto cleanup;
     ret = qemuMonitorSetPassword(priv->mon, type, password, connected);
 
@@ -5376,7 +5416,7 @@ qemuDomainChangeGraphicsPasswords(virQEMUDriverPtr driver,
     }
 
  end_job:
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
  cleanup:
     VIR_FREE(validTo);
@@ -5439,6 +5479,7 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
     virDomainDefPtr vmdef = vm->def;
     virDomainChrDefPtr tmpChr;
     char *devstr = NULL;
+    qemuMonitorPtr mon;
 
     if (!(tmpChr = virDomainChrFind(vmdef, chr))) {
         virReportError(VIR_ERR_DEVICE_MISSING,
@@ -5458,12 +5499,12 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
 
     qemuDomainMarkDeviceForRemoval(vm, &tmpChr->info);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     if (devstr && qemuMonitorDelDevice(priv->mon, tmpChr->info.alias) < 0) {
-        ignore_value(qemuDomainObjExitMonitor(driver, vm));
+        ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
         goto cleanup;
     }
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1) {
@@ -5488,6 +5529,7 @@ qemuDomainDetachRNGDevice(virQEMUDriverPtr driver,
     virDomainRNGDefPtr tmpRNG;
     int rc;
     int ret = -1;
+    qemuMonitorPtr mon;
 
     if ((idx = virDomainRNGFind(vm->def, rng)) < 0) {
         virReportError(VIR_ERR_DEVICE_MISSING,
@@ -5507,9 +5549,9 @@ qemuDomainDetachRNGDevice(virQEMUDriverPtr driver,
 
     qemuDomainMarkDeviceForRemoval(vm, &tmpRNG->info);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     rc = qemuMonitorDelDevice(priv->mon, tmpRNG->info.alias);
-    if (qemuDomainObjExitMonitor(driver, vm) || rc < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) || rc < 0)
         goto cleanup;
 
     if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
@@ -5531,6 +5573,7 @@ qemuDomainDetachMemoryDevice(virQEMUDriverPtr driver,
     int idx;
     int rc;
     int ret = -1;
+    qemuMonitorPtr mon;
 
     qemuDomainMemoryDeviceAlignSize(vm->def, memdef);
 
@@ -5552,9 +5595,9 @@ qemuDomainDetachMemoryDevice(virQEMUDriverPtr driver,
 
     qemuDomainMarkDeviceForRemoval(vm, &mem->info);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     rc = qemuMonitorDelDevice(priv->mon, mem->info.alias);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || rc < 0)
         goto cleanup;
 
     if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
@@ -5645,6 +5688,7 @@ qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver,
     unsigned int nvcpus = vcpupriv->vcpus;
     int rc;
     int ret = -1;
+    qemuMonitorPtr mon;
 
     if (!vcpupriv->alias) {
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
@@ -5654,11 +5698,11 @@ qemuDomainHotplugDelVcpu(virQEMUDriverPtr driver,
 
     qemuDomainMarkDeviceAliasForRemoval(vm, vcpupriv->alias);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     rc = qemuMonitorDelDevice(qemuDomainGetMonitor(vm), vcpupriv->alias);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     if (rc < 0) {
@@ -5705,6 +5749,7 @@ qemuDomainHotplugAddVcpu(virQEMUDriverPtr driver,
     int rc;
     int oldvcpus = virDomainDefGetVcpus(vm->def);
     size_t i;
+    qemuMonitorPtr mon;
 
     if (newhotplug) {
         if (virAsprintf(&vcpupriv->alias, "vcpu%u", vcpu) < 0)
@@ -5714,7 +5759,7 @@ qemuDomainHotplugAddVcpu(virQEMUDriverPtr driver,
             goto cleanup;
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     if (newhotplug) {
         rc = qemuMonitorAddDeviceArgs(qemuDomainGetMonitor(vm), vcpuprops);
@@ -5723,7 +5768,7 @@ qemuDomainHotplugAddVcpu(virQEMUDriverPtr driver,
         rc = qemuMonitorSetCPU(qemuDomainGetMonitor(vm), vcpu, true);
     }
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     virDomainAuditVcpu(vm, oldvcpus, oldvcpus + nvcpus, "update", rc == 0);
@@ -6236,6 +6281,7 @@ qemuDomainDetachInputDevice(virDomainObjPtr vm,
     virDomainInputDefPtr input;
     int ret = -1;
     int idx;
+    qemuMonitorPtr mon;
 
     if ((idx = virDomainInputDefFind(vm->def, def)) < 0) {
         virReportError(VIR_ERR_OPERATION_FAILED, "%s",
@@ -6261,12 +6307,12 @@ qemuDomainDetachInputDevice(virDomainObjPtr vm,
 
     qemuDomainMarkDeviceForRemoval(vm, &input->info);
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorDelDevice(priv->mon, input->info.alias)) {
-        ignore_value(qemuDomainObjExitMonitor(driver, vm));
+        ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
         goto cleanup;
     }
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
 
     if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
old mode 100644
new mode 100755
index 5ee9e5c..9acff21
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -106,8 +106,9 @@ qemuMigrationCheckTLSCreds(virQEMUDriverPtr driver,
     int ret = -1;
     qemuDomainObjPrivatePtr priv = vm->privateData;
     qemuMonitorMigrationParams migParams = { 0 };
+    qemuMonitorPtr mon;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     if (qemuMonitorGetMigrationParams(priv->mon, &migParams) < 0)
@@ -119,7 +120,7 @@ qemuMigrationCheckTLSCreds(virQEMUDriverPtr driver,
     ret = 0;
 
  cleanup:
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
     qemuMigrationParamsClear(&migParams);
@@ -501,6 +502,7 @@ qemuMigrationStartNBDServer(virQEMUDriverPtr driver,
     unsigned short port = 0;
     char *diskAlias = NULL;
     size_t i;
+    qemuMonitorPtr mon;
 
     if (nbdPort < 0 || nbdPort > USHRT_MAX) {
         virReportError(VIR_ERR_INVALID_ARG, "%s",
@@ -527,7 +529,7 @@ qemuMigrationStartNBDServer(virQEMUDriverPtr driver,
             goto cleanup;
 
         if (qemuDomainObjEnterMonitorAsync(driver, vm,
-                                           QEMU_ASYNC_JOB_MIGRATION_IN) < 0)
+                                           QEMU_ASYNC_JOB_MIGRATION_IN, &mon) < 0)
             goto cleanup;
 
         if (port == 0) {
@@ -542,7 +544,7 @@ qemuMigrationStartNBDServer(virQEMUDriverPtr driver,
 
         if (qemuMonitorNBDServerAdd(priv->mon, diskAlias, true) < 0)
             goto exit_monitor;
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             goto cleanup;
     }
 
@@ -556,7 +558,7 @@ qemuMigrationStartNBDServer(virQEMUDriverPtr driver,
     return ret;
 
  exit_monitor:
-    ignore_value(qemuDomainObjExitMonitor(driver, vm));
+    ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
     goto cleanup;
 }
 
@@ -567,17 +569,18 @@ qemuMigrationStopNBDServer(virQEMUDriverPtr driver,
                            qemuMigrationCookiePtr mig)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    qemuMonitorPtr mon;
 
     if (!mig->nbd)
         return 0;
 
     if (qemuDomainObjEnterMonitorAsync(driver, vm,
-                                       QEMU_ASYNC_JOB_MIGRATION_IN) < 0)
+                                       QEMU_ASYNC_JOB_MIGRATION_IN, &mon) < 0)
         return -1;
 
     if (qemuMonitorNBDServerStop(priv->mon) < 0)
         VIR_WARN("Unable to stop NBD server");
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         return -1;
 
     virPortAllocatorRelease(driver->migrationPorts, priv->nbdPort);
@@ -756,6 +759,7 @@ qemuMigrationCancelOneDriveMirror(virQEMUDriverPtr driver,
     int ret = -1;
     int status;
     int rv;
+    qemuMonitorPtr mon;
 
     status = qemuBlockJobUpdate(driver, vm, asyncJob, disk, &error);
     switch (status) {
@@ -781,12 +785,12 @@ qemuMigrationCancelOneDriveMirror(virQEMUDriverPtr driver,
     if (!(diskAlias = qemuAliasFromDisk(disk)))
         return -1;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         goto cleanup;
 
     rv = qemuMonitorBlockJobCancel(priv->mon, diskAlias);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || rv < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || rv < 0)
         goto cleanup;
 
     ret = 0;
@@ -920,6 +924,7 @@ qemuMigrationDriveMirror(virQEMUDriverPtr driver,
     unsigned int mirror_flags = VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT;
     int rv;
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+    qemuMonitorPtr mon;
 
     VIR_DEBUG("Starting drive mirrors for domain %s", vm->def->name);
 
@@ -961,7 +966,7 @@ qemuMigrationDriveMirror(virQEMUDriverPtr driver,
             goto cleanup;
 
         if (qemuDomainObjEnterMonitorAsync(driver, vm,
-                                           QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
+                                           QEMU_ASYNC_JOB_MIGRATION_OUT, &mon) < 0)
             goto cleanup;
 
         qemuBlockJobSyncBegin(disk);
@@ -971,7 +976,7 @@ qemuMigrationDriveMirror(virQEMUDriverPtr driver,
         VIR_FREE(diskAlias);
         VIR_FREE(nbd_dest);
 
-        if (qemuDomainObjExitMonitor(driver, vm) < 0 || mon_ret < 0) {
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || mon_ret < 0) {
             qemuBlockJobSyncEnd(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT, disk);
             goto cleanup;
         }
@@ -1296,6 +1301,7 @@ qemuMigrationSetOption(virQEMUDriverPtr driver,
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int ret;
+    qemuMonitorPtr mon;
 
     if (!qemuMigrationCapsGet(vm, capability)) {
         if (!state) {
@@ -1317,12 +1323,12 @@ qemuMigrationSetOption(virQEMUDriverPtr driver,
         return -1;
     }
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, job) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, job, &mon) < 0)
         return -1;
 
     ret = qemuMonitorSetMigrationCapability(priv->mon, capability, state);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
     return ret;
@@ -1416,13 +1422,14 @@ qemuMigrationFetchStats(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     qemuMonitorMigrationStats stats;
     int rv;
+    qemuMonitorPtr mon;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     rv = qemuMonitorGetMigrationStats(priv->mon, &stats, error);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || rv < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || rv < 0)
         return -1;
 
     jobInfo->stats.mig = stats;
@@ -1702,6 +1709,7 @@ qemuDomainMigrateGraphicsRelocate(virQEMUDriverPtr driver,
     int port = -1;
     int tlsPort = -1;
     const char *tlsSubject = NULL;
+    qemuMonitorPtr mon;
 
     if (!cookie || (!cookie->graphics && !graphicsuri))
         return 0;
@@ -1772,11 +1780,11 @@ qemuDomainMigrateGraphicsRelocate(virQEMUDriverPtr driver,
     }
 
     if (qemuDomainObjEnterMonitorAsync(driver, vm,
-                                       QEMU_ASYNC_JOB_MIGRATION_OUT) == 0) {
+                                       QEMU_ASYNC_JOB_MIGRATION_OUT, &mon) == 0) {
         ret = qemuMonitorGraphicsRelocate(priv->mon, type, listenAddress,
                                           port, tlsPort, tlsSubject);
         priv->job.spiceMigration = !ret;
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             ret = -1;
     }
 
@@ -1872,15 +1880,16 @@ qemuMigrationRunIncoming(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int ret = -1;
     int rv;
+    qemuMonitorPtr mon;
 
     VIR_DEBUG("Setting up incoming migration with URI %s", uri);
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     rv = qemuMonitorMigrateIncoming(priv->mon, uri);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || rv < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || rv < 0)
         goto cleanup;
 
     if (asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN) {
@@ -2326,6 +2335,7 @@ qemuMigrationSetCompression(virQEMUDriverPtr driver,
 {
     int ret = -1;
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    qemuMonitorPtr mon;
 
     if (qemuMigrationSetOption(driver, vm,
                                QEMU_MONITOR_MIGRATION_CAPS_XBZRLE,
@@ -2341,7 +2351,7 @@ qemuMigrationSetCompression(virQEMUDriverPtr driver,
                                job) < 0)
         return -1;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, job) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, job, &mon) < 0)
         return -1;
 
     migParams->compressLevel_set = compression->level_set;
@@ -2361,7 +2371,7 @@ qemuMigrationSetCompression(virQEMUDriverPtr driver,
     ret = 0;
 
  cleanup:
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
     return ret;
@@ -2478,8 +2488,9 @@ qemuMigrationSetParams(virQEMUDriverPtr driver,
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int ret = -1;
+    qemuMonitorPtr mon;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, job) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, job, &mon) < 0)
         return -1;
 
     if (qemuMonitorSetMigrationParams(priv->mon, migParams) < 0)
@@ -2488,7 +2499,7 @@ qemuMigrationSetParams(virQEMUDriverPtr driver,
     ret = 0;
 
  cleanup:
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
     return ret;
@@ -3644,13 +3655,14 @@ qemuMigrationContinue(virQEMUDriverPtr driver,
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int ret;
+    qemuMonitorPtr mon;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     ret = qemuMonitorMigrateContinue(priv->mon, status);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
     return ret;
@@ -3694,6 +3706,7 @@ qemuMigrationRun(virQEMUDriverPtr driver,
     virDomainDefPtr persistDef = NULL;
     char *timestamp;
     int rc;
+    qemuMonitorPtr mon;
 
     VIR_DEBUG("driver=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
               "cookieout=%p, cookieoutlen=%p, flags=0x%lx, resource=%lu, "
@@ -3836,7 +3849,7 @@ qemuMigrationRun(virQEMUDriverPtr driver,
         goto error;
 
     if (qemuDomainObjEnterMonitorAsync(driver, vm,
-                                       QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
+                                       QEMU_ASYNC_JOB_MIGRATION_OUT, &mon) < 0)
         goto error;
 
     if (priv->job.abortJob) {
@@ -3893,7 +3906,7 @@ qemuMigrationRun(virQEMUDriverPtr driver,
         break;
     }
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || rc < 0)
         goto error;
 
     /* From this point onwards we *must* call cancel to abort the
@@ -4026,9 +4039,9 @@ qemuMigrationRun(virQEMUDriverPtr driver,
         priv->job.current->status != QEMU_DOMAIN_JOB_STATUS_QEMU_COMPLETED &&
         virDomainObjIsActive(vm) &&
         qemuDomainObjEnterMonitorAsync(driver, vm,
-                                       QEMU_ASYNC_JOB_MIGRATION_OUT) == 0) {
+                                       QEMU_ASYNC_JOB_MIGRATION_OUT, &mon) == 0) {
         qemuMonitorMigrateCancel(priv->mon);
-        ignore_value(qemuDomainObjExitMonitor(driver, vm));
+        ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
     }
 
     /* cancel any outstanding NBD jobs */
@@ -4046,7 +4059,7 @@ qemuMigrationRun(virQEMUDriverPtr driver,
     goto cleanup;
 
  exit_monitor:
-    ignore_value(qemuDomainObjExitMonitor(driver, vm));
+    ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
     goto error;
 }
 
@@ -5550,14 +5563,15 @@ qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm,
     unsigned long saveMigBandwidth = priv->migMaxBandwidth;
     char *errbuf = NULL;
     virErrorPtr orig_err = NULL;
+    qemuMonitorPtr mon;
 
     /* Increase migration bandwidth to unlimited since target is a file.
      * Failure to change migration speed is not fatal. */
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) == 0) {
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) == 0) {
         qemuMonitorSetMigrationSpeed(priv->mon,
                                      QEMU_DOMAIN_MIG_BANDWIDTH_MAX);
         priv->migMaxBandwidth = QEMU_DOMAIN_MIG_BANDWIDTH_MAX;
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             return -1;
     }
 
@@ -5582,7 +5596,7 @@ qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm,
                                     compressor ? pipeFD[1] : fd) < 0)
         goto cleanup;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         goto cleanup;
 
     if (!compressor) {
@@ -5605,11 +5619,11 @@ qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm,
         if (virSetCloseExec(pipeFD[1]) < 0) {
             virReportSystemError(errno, "%s",
                                  _("Unable to set cloexec flag"));
-            ignore_value(qemuDomainObjExitMonitor(driver, vm));
+            ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
             goto cleanup;
         }
         if (virCommandRunAsync(cmd, NULL) < 0) {
-            ignore_value(qemuDomainObjExitMonitor(driver, vm));
+            ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
             goto cleanup;
         }
         rc = qemuMonitorMigrateToFd(priv->mon,
@@ -5619,7 +5633,7 @@ qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm,
             VIR_CLOSE(pipeFD[1]) < 0)
             VIR_WARN("failed to close intermediate pipe");
     }
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
     if (rc < 0)
         goto cleanup;
@@ -5631,9 +5645,9 @@ qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm,
             orig_err = virSaveLastError();
             virCommandAbort(cmd);
             if (virDomainObjIsActive(vm) &&
-                qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) == 0) {
+                qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) == 0) {
                 qemuMonitorMigrateCancel(priv->mon);
-                ignore_value(qemuDomainObjExitMonitor(driver, vm));
+                ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
             }
         }
         goto cleanup;
@@ -5651,10 +5665,10 @@ qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm,
 
     /* Restore max migration bandwidth */
     if (virDomainObjIsActive(vm) &&
-        qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) == 0) {
+        qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) == 0) {
         qemuMonitorSetMigrationSpeed(priv->mon, saveMigBandwidth);
         priv->migMaxBandwidth = saveMigBandwidth;
-        ignore_value(qemuDomainObjExitMonitor(driver, vm));
+        ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
     }
 
     VIR_FORCE_CLOSE(pipeFD[0]);
@@ -5683,6 +5697,7 @@ qemuMigrationCancel(virQEMUDriverPtr driver,
     bool storage = false;
     size_t i;
     int ret = -1;
+    qemuMonitorPtr mon;
 
     VIR_DEBUG("Canceling unfinished outgoing migration of domain %s",
               vm->def->name);
@@ -5695,13 +5710,13 @@ qemuMigrationCancel(virQEMUDriverPtr driver,
         }
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
 
     ignore_value(qemuMonitorMigrateCancel(priv->mon));
     if (storage)
         blockJobs = qemuMonitorGetAllBlockJobInfo(priv->mon);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || (storage && !blockJobs))
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || (storage && !blockJobs))
         goto endsyncjob;
 
     if (!storage) {
@@ -6071,6 +6086,7 @@ qemuMigrationFetchMirrorStats(virQEMUDriverPtr driver,
     bool nbd = false;
     virHashTablePtr blockinfo = NULL;
     qemuDomainMirrorStatsPtr stats = &jobInfo->mirrorStats;
+    qemuMonitorPtr mon;
 
     for (i = 0; i < vm->def->ndisks; i++) {
         virDomainDiskDefPtr disk = vm->def->disks[i];
@@ -6083,12 +6099,12 @@ qemuMigrationFetchMirrorStats(virQEMUDriverPtr driver,
     if (!nbd)
         return 0;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     blockinfo = qemuMonitorGetAllBlockJobInfo(priv->mon);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || !blockinfo)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || !blockinfo)
         return -1;
 
     memset(stats, 0, sizeof(*stats));
diff --git a/src/qemu/qemu_migration_cookie.c b/src/qemu/qemu_migration_cookie.c
old mode 100644
new mode 100755
index 945530c..27003c6
--- a/src/qemu/qemu_migration_cookie.c
+++ b/src/qemu/qemu_migration_cookie.c
@@ -452,6 +452,7 @@ qemuMigrationCookieAddNBD(qemuMigrationCookiePtr mig,
     virHashTablePtr stats = NULL;
     size_t i;
     int ret = -1, rc;
+    qemuMonitorPtr mon;
 
     /* It is not a bug if there already is a NBD data */
     qemuMigrationCookieNBDFree(mig->nbd);
@@ -473,10 +474,10 @@ qemuMigrationCookieAddNBD(qemuMigrationCookiePtr mig,
                 goto cleanup;
 
             if (qemuDomainObjEnterMonitorAsync(driver, vm,
-                                               priv->job.asyncJob) < 0)
+                                               priv->job.asyncJob, &mon) < 0)
                 goto cleanup;
             rc = qemuMonitorBlockStatsUpdateCapacity(priv->mon, stats, false);
-            if (qemuDomainObjExitMonitor(driver, vm) < 0)
+            if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
                 goto cleanup;
             if (rc < 0)
                 goto cleanup;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
old mode 100644
new mode 100755
index c1da3bb..6961348
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -543,6 +543,7 @@ qemuProcessFakeReboot(void *opaque)
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
     virDomainRunningReason reason = VIR_DOMAIN_RUNNING_BOOTED;
     int ret = -1, rc;
+    qemuMonitorPtr mon;
 
     VIR_DEBUG("vm=%p", vm);
     virObjectLock(vm);
@@ -555,10 +556,10 @@ qemuProcessFakeReboot(void *opaque)
         goto endjob;
     }
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     rc = qemuMonitorSystemReset(priv->mon);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto endjob;
 
     if (rc < 0)
@@ -1767,13 +1768,14 @@ qemuProcessInitMonitor(virQEMUDriverPtr driver,
                        qemuDomainAsyncJob asyncJob)
 {
     int ret;
+    qemuMonitorPtr mon;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     ret = qemuMonitorSetCapabilities(QEMU_DOMAIN_PRIVATE(vm)->mon);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
     return ret;
@@ -2094,12 +2096,13 @@ qemuRefreshVirtioChannelState(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virHashTablePtr info = NULL;
     int ret = -1;
+    qemuMonitorPtr mon;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         goto cleanup;
 
     ret = qemuMonitorGetChardevInfo(priv->mon, &info);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
     if (ret < 0)
@@ -2121,15 +2124,16 @@ qemuRefreshRTC(virQEMUDriverPtr driver,
     struct tm thenbits;
     long localOffset;
     int rv;
+    qemuMonitorPtr mon;
 
     if (vm->def->clock.offset != VIR_DOMAIN_CLOCK_OFFSET_VARIABLE)
         return;
 
     memset(&thenbits, 0, sizeof(thenbits));
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     now = time(NULL);
     rv = qemuMonitorGetRTCTime(priv->mon, &thenbits);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         rv = -1;
 
     if (rv < 0)
@@ -2156,6 +2160,7 @@ qemuProcessRefreshBalloonState(virQEMUDriverPtr driver,
 {
     unsigned long long balloon;
     int rc;
+    qemuMonitorPtr mon;
 
     /* if no ballooning is available, the current size equals to the current
      * full memory size */
@@ -2164,11 +2169,11 @@ qemuProcessRefreshBalloonState(virQEMUDriverPtr driver,
         return 0;
     }
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     rc = qemuMonitorGetBalloonInfo(qemuDomainGetMonitor(vm), &balloon);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0 || rc < 0)
         return -1;
 
     vm->def->mem.cur_balloon = balloon;
@@ -2186,6 +2191,7 @@ qemuProcessWaitForMonitor(virQEMUDriverPtr driver,
     int ret = -1;
     virHashTablePtr info = NULL;
     qemuDomainObjPrivatePtr priv;
+    qemuMonitorPtr mon;
 
     VIR_DEBUG("Connect monitor to %p '%s'", vm, vm->def->name);
     if (qemuConnectMonitor(driver, vm, asyncJob, logCtxt) < 0)
@@ -2196,11 +2202,11 @@ qemuProcessWaitForMonitor(virQEMUDriverPtr driver,
      * Note that the monitor itself can be on a pty, so we still need to try the
      * log output method. */
     priv = vm->privateData;
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         goto cleanup;
     ret = qemuMonitorGetChardevInfo(priv->mon, &info);
     VIR_DEBUG("qemuMonitorGetChardevInfo returned %i", ret);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
     if (ret == 0) {
@@ -2235,6 +2241,7 @@ qemuProcessDetectIOThreadPIDs(virQEMUDriverPtr driver,
     int niothreads = 0;
     int ret = -1;
     size_t i;
+    qemuMonitorPtr mon;
 
     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD)) {
         ret = 0;
@@ -2242,10 +2249,10 @@ qemuProcessDetectIOThreadPIDs(virQEMUDriverPtr driver,
     }
 
     /* Get the list of IOThreads from qemu */
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         goto cleanup;
     niothreads = qemuMonitorGetIOThreads(priv->mon, &iothreads);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto cleanup;
     if (niothreads < 0)
         goto cleanup;
@@ -2374,8 +2381,9 @@ qemuProcessSetLinkStates(virQEMUDriverPtr driver,
     size_t i;
     int ret = -1;
     int rv;
+    qemuMonitorPtr mon;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     for (i = 0; i < def->nnets; i++) {
@@ -2409,7 +2417,7 @@ qemuProcessSetLinkStates(virQEMUDriverPtr driver,
     ret = 0;
 
  cleanup:
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
     return ret;
 }
@@ -2578,6 +2586,7 @@ qemuProcessInitPasswords(virConnectPtr conn,
     size_t i;
     char *alias = NULL;
     char *secret = NULL;
+    qemuMonitorPtr mon;
 
     for (i = 0; i < vm->def->ngraphics; ++i) {
         virDomainGraphicsDefPtr graphics = vm->def->graphics[i];
@@ -2621,10 +2630,10 @@ qemuProcessInitPasswords(virConnectPtr conn,
         VIR_FREE(alias);
         if (!(alias = qemuAliasFromDisk(vm->def->disks[i])))
             goto cleanup;
-        if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+        if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
             goto cleanup;
         ret = qemuMonitorSetDrivePassphrase(priv->mon, alias, secret);
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             ret = -1;
         if (ret < 0)
             goto cleanup;
@@ -2695,8 +2704,9 @@ qemuProcessUpdateVideoRamSize(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virDomainVideoDefPtr video = NULL;
     virQEMUDriverConfigPtr cfg = NULL;
+    qemuMonitorPtr mon;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     for (i = 0; i < vm->def->nvideos; i++) {
@@ -2748,7 +2758,7 @@ qemuProcessUpdateVideoRamSize(virQEMUDriverPtr driver,
 
     }
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         return -1;
 
     cfg = virQEMUDriverGetConfig(driver);
@@ -2758,7 +2768,7 @@ qemuProcessUpdateVideoRamSize(virQEMUDriverPtr driver,
     return ret;
 
  error:
-    ignore_value(qemuDomainObjExitMonitor(driver, vm));
+    ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
     return -1;
 }
 
@@ -2862,6 +2872,7 @@ qemuProcessStartCPUs(virQEMUDriverPtr driver, virDomainObjPtr vm,
     int ret = -1;
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+    qemuMonitorPtr mon;
 
     /* Bring up netdevs before starting CPUs */
     if (qemuInterfaceStartDevices(vm->def) < 0)
@@ -2878,11 +2889,11 @@ qemuProcessStartCPUs(virQEMUDriverPtr driver, virDomainObjPtr vm,
     }
     VIR_FREE(priv->lockState);
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         goto release;
 
     ret = qemuMonitorStartCPUs(priv->mon, conn);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
     if (ret < 0)
@@ -2909,14 +2920,15 @@ int qemuProcessStopCPUs(virQEMUDriverPtr driver,
 {
     int ret = -1;
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    qemuMonitorPtr mon;
 
     VIR_FREE(priv->lockState);
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         goto cleanup;
 
     ret = qemuMonitorStopCPUs(priv->mon);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
 
     if (ret < 0)
@@ -2986,10 +2998,11 @@ qemuProcessUpdateState(virQEMUDriverPtr driver, virDomainObjPtr vm)
     bool running;
     char *msg = NULL;
     int ret;
+    qemuMonitorPtr mon;
 
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     ret = qemuMonitorGetStatus(priv->mon, &running, &reason);
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         return -1;
 
     if (ret < 0)
@@ -3203,6 +3216,7 @@ qemuProcessRecoverJob(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virDomainState state;
     int reason;
+    qemuMonitorPtr mon;
 
     state = virDomainObjGetState(vm, &reason);
 
@@ -3222,9 +3236,9 @@ qemuProcessRecoverJob(virQEMUDriverPtr driver,
     case QEMU_ASYNC_JOB_SAVE:
     case QEMU_ASYNC_JOB_DUMP:
     case QEMU_ASYNC_JOB_SNAPSHOT:
-        qemuDomainObjEnterMonitor(driver, vm);
+        mon = qemuDomainObjEnterMonitor(driver, vm);
         ignore_value(qemuMonitorMigrateCancel(priv->mon));
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             return -1;
         /* resume the domain but only if it was paused as a result of
          * running a migration-to-file operation.  Although we are
@@ -3814,6 +3828,7 @@ qemuProcessFetchGuestCPU(virQEMUDriverPtr driver,
     virCPUDataPtr dataEnabled = NULL;
     virCPUDataPtr dataDisabled = NULL;
     int rc;
+    qemuMonitorPtr mon;
 
     *enabled = NULL;
     *disabled = NULL;
@@ -3821,13 +3836,13 @@ qemuProcessFetchGuestCPU(virQEMUDriverPtr driver,
     if (!ARCH_IS_X86(vm->def->os.arch))
         return 0;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         goto error;
 
     rc = qemuMonitorGetGuestCPU(priv->mon, vm->def->os.arch,
                                 &dataEnabled, &dataDisabled);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto error;
 
     if (rc == -1)
@@ -3945,13 +3960,14 @@ qemuProcessFetchCPUDefinitions(virQEMUDriverPtr driver,
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
     virDomainCapsCPUModelsPtr models = NULL;
+    qemuMonitorPtr mon;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         goto error;
 
     models = virQEMUCapsFetchCPUDefinitions(priv->mon);
 
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto error;
 
     return models;
@@ -4569,11 +4585,12 @@ qemuProcessSetupBalloon(virQEMUDriverPtr driver,
     unsigned long long balloon = vm->def->mem.cur_balloon;
     qemuDomainObjPrivatePtr priv = vm->privateData;
     int ret = -1;
+    qemuMonitorPtr mon;
 
     if (!virDomainDefHasMemballoon(vm->def))
         return 0;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
         return -1;
 
     if (vm->def->memballoon->period)
@@ -4585,7 +4602,7 @@ qemuProcessSetupBalloon(virQEMUDriverPtr driver,
     ret = 0;
 
  cleanup:
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         ret = -1;
     return ret;
 }
@@ -5322,6 +5339,7 @@ qemuProcessSetupHotpluggableVcpus(virQEMUDriverPtr driver,
     size_t i;
     int ret = -1;
     int rc;
+    qemuMonitorPtr mon;
 
     virDomainVcpuDefPtr *bootHotplug = NULL;
     size_t nbootHotplug = 0;
@@ -5357,13 +5375,13 @@ qemuProcessSetupHotpluggableVcpus(virQEMUDriverPtr driver,
         if (!(vcpuprops = qemuBuildHotpluggableCPUProps(vcpu)))
             goto cleanup;
 
-        if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+        if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) < 0)
             goto cleanup;
 
         rc = qemuMonitorAddDeviceArgs(qemuDomainGetMonitor(vm), vcpuprops);
         vcpuprops = NULL;
 
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             goto cleanup;
 
         if (rc < 0)
@@ -6765,6 +6783,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
     virCapsPtr caps = NULL;
     bool active = false;
+    qemuMonitorPtr mon;
 
     VIR_DEBUG("Beginning VM attach process");
 
@@ -6911,14 +6930,14 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
         goto error;
 
     VIR_DEBUG("Getting initial memory amount");
-    qemuDomainObjEnterMonitor(driver, vm);
+    mon = qemuDomainObjEnterMonitor(driver, vm);
     if (qemuMonitorGetBalloonInfo(priv->mon, &vm->def->mem.cur_balloon) < 0)
         goto exit_monitor;
     if (qemuMonitorGetStatus(priv->mon, &running, &reason) < 0)
         goto exit_monitor;
     if (qemuMonitorGetVirtType(priv->mon, &vm->def->virtType) < 0)
         goto exit_monitor;
-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+    if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
         goto error;
 
     if (running) {
@@ -6927,10 +6946,10 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
         if (vm->def->memballoon &&
             vm->def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO &&
             vm->def->memballoon->period) {
-            qemuDomainObjEnterMonitor(driver, vm);
+            mon = qemuDomainObjEnterMonitor(driver, vm);
             qemuMonitorSetMemoryStatsPeriod(priv->mon, vm->def->memballoon,
                                             vm->def->memballoon->period);
-            if (qemuDomainObjExitMonitor(driver, vm) < 0)
+            if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
                 goto error;
         }
     } else {
@@ -6967,7 +6986,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
     return 0;
 
  exit_monitor:
-    ignore_value(qemuDomainObjExitMonitor(driver, vm));
+    ignore_value(qemuDomainObjExitMonitor(driver, vm, mon));
  error:
     /* We jump here if we failed to attach to the VM for any reason.
      * Leave the domain running, but pretend we never attempted to
@@ -7075,10 +7094,11 @@ qemuProcessRefreshDisks(virQEMUDriverPtr driver,
     virHashTablePtr table = NULL;
     int ret = -1;
     size_t i;
+    qemuMonitorPtr mon;
 
-    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) == 0) {
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob, &mon) == 0) {
         table = qemuMonitorGetBlockInfo(priv->mon);
-        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        if (qemuDomainObjExitMonitor(driver, vm, mon) < 0)
             goto cleanup;
     }
 
-- 
1.8.3.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] qemu: monitor: fix unsafe monitor access
Posted by Peter Krempa 6 years, 1 month ago
On Thu, Mar 01, 2018 at 01:09:40 +0800, Peng Hao wrote:
> From: root <root@localhost.localdomain>
> 
> qemuDomainObjExitMonitor is unsafe
> 
> domain lock released when qemuDomainObjEnterMonitor finish,
> So other thread (qemuProcessStop) has chance to modify priv->mon
> to NULL. qemuDomainObjExitMonitor will never release the mon->lock,
> 
> that may cause problem:
> thread get monitor ptr early, and then try to get mon->lock,
> it will block forerver cause mon->lock not released by
> qemuDomainObjExitMonitor.

Could you please provide a reproducer for this? The call to
qemuProcessStop should be guarded by a domain job, which should
guarantee that priv->mon is unset only after the currently processed
monitor call exits properly.
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] qemu: monitor: fix unsafe monitor access
Posted by Michal Privoznik 6 years, 1 month ago
On 02/28/2018 06:09 PM, Peng Hao wrote:
> From: root <root@localhost.localdomain>

Don't you want to take credit for the patch?

git config --global user.name "Mona Lisa"
git config --global user.email "email@example.com"

> 
> qemuDomainObjExitMonitor is unsafe
> 
> domain lock released when qemuDomainObjEnterMonitor finish,
> So other thread (qemuProcessStop) has chance to modify priv->mon
> to NULL. qemuDomainObjExitMonitor will never release the mon->lock,
> 
> that may cause problem:
> thread get monitor ptr early, and then try to get mon->lock,
> it will block forerver cause mon->lock not released by
> qemuDomainObjExitMonitor.

I don't quite understand. There can be only one thread talking to
monitor, and actually only one thread calling
qemuDomainObjEnterMonitor(). Because in order to call EnterMonitor() the
caller needs to have domainObj lock. So there can be only one thread
holding the domainObj lock and another which holds the monitor lock. I'm
failing to see why not unlocking monitor would be a problem. Do you
perhaps have a reproducer?

> 
> Signed-off-by: Wang Yechao <wang.yechao255@zte.com.cn>
> Signed-off-by: Peng Hao <peng.hao2@zte.com.cn>
> ---
>  src/qemu/THREADS.txt             |  12 +-
>  src/qemu/qemu_block.c            |   5 +-
>  src/qemu/qemu_domain.c           |  64 +++++----
>  src/qemu/qemu_domain.h           |  12 +-
>  src/qemu/qemu_driver.c           | 258 ++++++++++++++++++++--------------
>  src/qemu/qemu_hotplug.c          | 296 ++++++++++++++++++++++-----------------
>  src/qemu/qemu_migration.c        | 104 ++++++++------
>  src/qemu/qemu_migration_cookie.c |   5 +-
>  src/qemu/qemu_process.c          | 108 ++++++++------
>  9 files changed, 507 insertions(+), 357 deletions(-)

This fails to apply cleanly. Can you please rebase?

>  mode change 100644 => 100755 src/qemu/THREADS.txt
>  mode change 100644 => 100755 src/qemu/qemu_block.c
>  mode change 100644 => 100755 src/qemu/qemu_domain.c
>  mode change 100644 => 100755 src/qemu/qemu_domain.h
>  mode change 100644 => 100755 src/qemu/qemu_driver.c
>  mode change 100644 => 100755 src/qemu/qemu_hotplug.c
>  mode change 100644 => 100755 src/qemu/qemu_migration.c
>  mode change 100644 => 100755 src/qemu/qemu_migration_cookie.c
>  mode change 100644 => 100755 src/qemu/qemu_process.c

No. This is not what we want. We don't need *.c files executable.

Michal

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] qemu: monitor: fix unsafe monitor access
Posted by Daniel P. Berrangé 6 years, 1 month ago
On Thu, Mar 01, 2018 at 01:09:40AM +0800, Peng Hao wrote:
> From: root <root@localhost.localdomain>

You'll be wanting to fix your git author settings and then run
"git commit --reset-author --amend" to fix existing commits.

BTW, the clock on your machine sending the mail also seems to be
incorrect by about 7 hours.

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list