[libvirt] [PATCH] fix libvirtd memory leak when client was killed by user at eventRegister sense

xinhua.Cao caoxinhua at huawei.com
Sat Oct 28 01:23:45 UTC 2017


【DTS/AR】:DTS2017102200357
【description】:当客户端注册libvirt事件后,将客户端进程Kill,libvirtd服务端会有内存泄露。

Change-Id: I7eeffb4f1ba46038cd41fd26e6725ad2943229a8
---
 daemon/remote.c | 52 ++++++++++++++++++++++++++++++++--------------------
 1 file changed, 32 insertions(+), 20 deletions(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index f67370f..4b8de85 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -1727,25 +1727,14 @@ void remoteRelayConnectionClosedEvent(virConnectPtr conn ATTRIBUTE_UNUSED, int r
                 VIR_WARN("unexpected %s event deregister failure", name);   \
         }                                                                   \
         VIR_FREE(eventCallbacks);                                           \
+        neventCallbacks = 0;                                                \
     } while (0);
 
-/*
- * You must hold lock for at least the client
- * We don't free stuff here, merely disconnect the client's
- * network socket & resources.
- * We keep the libvirt connection open until any async
- * jobs have finished, then clean it up elsewhere
- */
-void remoteClientFreeFunc(void *data)
+static void
+remoteFreePrivCallbacks(void *data)
 {
     struct daemonClientPrivate *priv = data;
-
-    /* Deregister event delivery callback */
-    if (priv->conn) {
-        virIdentityPtr sysident = virIdentityGetSystem();
-
-        virIdentitySetCurrent(sysident);
-
+    if (priv && priv->conn) {
         DEREG_CB(priv->conn, priv->domainEventCallbacks,
                  priv->ndomainEventCallbacks,
                  virConnectDomainEventDeregisterAny, "domain");
@@ -1764,6 +1753,27 @@ void remoteClientFreeFunc(void *data)
         DEREG_CB(priv->conn, priv->qemuEventCallbacks,
                  priv->nqemuEventCallbacks,
                  virConnectDomainQemuMonitorEventDeregister, "qemu monitor");
+    }
+}
+#undef DEREG_CB
+
+/*
+ * You must hold lock for at least the client
+ * We don't free stuff here, merely disconnect the client's
+ * network socket & resources.
+ * We keep the libvirt connection open until any async
+ * jobs have finished, then clean it up elsewhere
+ */
+void remoteClientFreeFunc(void *data)
+{
+    struct daemonClientPrivate *priv = data;
+
+    /* Deregister event delivery callback */
+    if (priv) {
+        virIdentityPtr sysident = virIdentityGetSystem();
+
+        virIdentitySetCurrent(sysident);
+        remoteFreePrivCallbacks(priv);
 
         if (priv->closeRegistered) {
             if (virConnectUnregisterCloseCallback(priv->conn,
@@ -1775,19 +1785,21 @@ void remoteClientFreeFunc(void *data)
 
         virIdentitySetCurrent(NULL);
         virObjectUnref(sysident);
-    }
 
-    VIR_FREE(priv->hmacSalt);
-    VIR_FREE(priv);
+        VIR_FREE(priv->hmacSalt);
+        VIR_FREE(priv);
+    }
 }
-#undef DEREG_CB
 
 
 static void remoteClientCloseFunc(virNetServerClientPtr client)
 {
     struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client);
 
-    daemonRemoveAllClientStreams(priv->streams);
+    if (priv) {
+        daemonRemoveAllClientStreams(priv->streams);
+        remoteFreePrivCallbacks(priv);
+    }
 }
 
 
-- 
2.8.3





More information about the libvir-list mailing list