Suppose that we have two hosts A and B, migrate VM from A to B
by virDomainMigrateToURI2.
1.qemuProcessLaunch was been called on host B with
VIR_QEMU_PROCESS_START_AUTODESTROY flag, and VM's object
reference was been increased in virCloseCallbacksSet called by
qemuProcessAutoDestroyAdd.
2. Restart host A's libvirtd service to interrupt migration job,
virCloseCallbacksRun was been called on host B by qemuConnectClose,
VM's virDriverCloseDef struct was been removed from connection
callback list before execute qemuProcessAutoDestroy callback function.
3. Then qemuProcessAutoDestroy was been called on host B to destroy
the transient VM.
-->qemuProcessAutoDestroy
-->qemuProcessStop
-->qemuProcessAutoDestroyRemove
-->virCloseCallbacksUnset
At last, VM's object reference has been decreased in
virCloseCallbacksUnset expectably, however VM's virDriverCloseDef
struct cannot be found in callback list[2] lead to VM's object leak.
Signed-off-by: Wang King <king.wang(a)huawei.com>
---
src/util/virclosecallbacks.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/src/util/virclosecallbacks.c b/src/util/virclosecallbacks.c
index 1fa9596..633b22c 100644
--- a/src/util/virclosecallbacks.c
+++ b/src/util/virclosecallbacks.c
@@ -331,17 +331,9 @@ virCloseCallbacksRun(virCloseCallbacksPtr closeCallbacks,
virObjectLock(closeCallbacks);
list = virCloseCallbacksGetForConn(closeCallbacks, conn);
- if (!list) {
- virObjectLock(closeCallbacks);
+ virObjectLock(closeCallbacks);
+ if (!list)
return;
- }
-
- for (i = 0; i < list->nentries; i++) {
- char uuidstr[VIR_UUID_STRING_BUFLEN];
- virUUIDFormat(list->entries[i].uuid, uuidstr);
- virHashRemoveEntry(closeCallbacks->list, uuidstr);
- }
- virObjectUnlock(closeCallbacks);
for (i = 0; i < list->nentries; i++) {
virDomainObjPtr vm;
@@ -358,6 +350,15 @@ virCloseCallbacksRun(virCloseCallbacksPtr closeCallbacks,
if (vm)
virObjectUnlock(vm);
}
+
+ virObjectLock(closeCallbacks);
+ for (i = 0; i < list->nentries; i++) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(list->entries[i].uuid, uuidstr);
+ virHashRemoveEntry(closeCallbacks->list, uuidstr);
+ }
+ virObjectUnlock(closeCallbacks);
+
VIR_FREE(list->entries);
VIR_FREE(list);
}
--
2.8.3