From: "Daniel P. Berrange" <berrange(a)redhat.com>
Every active stream results in a reference being held on the
virNetServerClientPtr object. This meant that if a client quit
with any streams active, although all I/O was stopped the
virNetServerClientPtr object would leak. This causes libvirtd
to leak any file handles associated with open streams when a
client quit
To fix this, when we call virNetServerClientClose there is a
callback invoked which lets the daemon release the streams
and thus the extra references
* daemon/remote.c: Add a hook to close all streams
* src/rpc/virnetserverclient.c, src/rpc/virnetserverclient.h:
Allow registration of a hook to trigger when closing client
---
daemon/remote.c | 13 ++++++++++---
src/rpc/virnetserverclient.c | 21 +++++++++++++++++++++
src/rpc/virnetserverclient.h | 5 +++++
3 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/daemon/remote.c b/daemon/remote.c
index ec261e2..0f088c6 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -419,8 +419,6 @@ static void remoteClientFreeFunc(void *data)
{
struct daemonClientPrivate *priv = data;
- daemonRemoveAllClientStreams(priv->streams);
-
/* Deregister event delivery callback */
if (priv->conn) {
int i;
@@ -441,6 +439,13 @@ static void remoteClientFreeFunc(void *data)
}
+static void remoteClientCloseFunc(virNetServerClientPtr client)
+{
+ struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client);
+
+ daemonRemoveAllClientStreams(priv->streams);
+}
+
int remoteClientInitHook(virNetServerPtr srv ATTRIBUTE_UNUSED,
virNetServerClientPtr client)
@@ -462,7 +467,9 @@ int remoteClientInitHook(virNetServerPtr srv ATTRIBUTE_UNUSED,
for (i = 0 ; i < VIR_DOMAIN_EVENT_ID_LAST ; i++)
priv->domainEventCallbackID[i] = -1;
- virNetServerClientSetPrivateData(client, priv, remoteClientFreeFunc);
+ virNetServerClientSetPrivateData(client, priv,
+ remoteClientFreeFunc);
+ virNetServerClientSetCloseHook(client, remoteClientCloseFunc);
return 0;
}
diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c
index e246fa5..a73b06d 100644
--- a/src/rpc/virnetserverclient.c
+++ b/src/rpc/virnetserverclient.c
@@ -97,6 +97,7 @@ struct _virNetServerClient
void *privateData;
virNetServerClientFreeFunc privateDataFreeFunc;
+ virNetServerClientCloseFunc privateDataCloseFunc;
};
@@ -492,6 +493,15 @@ void *virNetServerClientGetPrivateData(virNetServerClientPtr client)
}
+void virNetServerClientSetCloseHook(virNetServerClientPtr client,
+ virNetServerClientCloseFunc cf)
+{
+ virNetServerClientLock(client);
+ client->privateDataCloseFunc = cf;
+ virNetServerClientUnlock(client);
+}
+
+
void virNetServerClientSetDispatcher(virNetServerClientPtr client,
virNetServerClientDispatchFunc func,
void *opaque)
@@ -560,6 +570,8 @@ void virNetServerClientFree(virNetServerClientPtr client)
*/
void virNetServerClientClose(virNetServerClientPtr client)
{
+ virNetServerClientCloseFunc cf;
+
virNetServerClientLock(client);
VIR_DEBUG("client=%p refs=%d", client, client->refs);
if (!client->sock) {
@@ -567,6 +579,15 @@ void virNetServerClientClose(virNetServerClientPtr client)
return;
}
+ if (client->privateDataCloseFunc) {
+ cf = client->privateDataCloseFunc;
+ client->refs++;
+ virNetServerClientUnlock(client);
+ (cf)(client);
+ virNetServerClientLock(client);
+ client->refs--;
+ }
+
/* Do now, even though we don't close the socket
* until end, to ensure we don't get invoked
* again due to tls shutdown */
diff --git a/src/rpc/virnetserverclient.h b/src/rpc/virnetserverclient.h
index 3d2e1fb..bedb179 100644
--- a/src/rpc/virnetserverclient.h
+++ b/src/rpc/virnetserverclient.h
@@ -82,6 +82,11 @@ void virNetServerClientSetPrivateData(virNetServerClientPtr client,
virNetServerClientFreeFunc ff);
void *virNetServerClientGetPrivateData(virNetServerClientPtr client);
+typedef void (*virNetServerClientCloseFunc)(virNetServerClientPtr client);
+
+void virNetServerClientSetCloseHook(virNetServerClientPtr client,
+ virNetServerClientCloseFunc cf);
+
void virNetServerClientSetDispatcher(virNetServerClientPtr client,
virNetServerClientDispatchFunc func,
void *opaque);
--
1.7.6