From e06c8ede42fcdc4e29b58e49a4b3f93b2a2c5740 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 19 Jul 2011 14:13:32 +0100 Subject: [PATCH] Add an explicit virNetClientClose method Since the I/O callback registered against virNetSocket will hold a reference on the virNetClient, we can't rely on the virNetClientFree to be able to close the network connection. The last reference will only go away when the event callback fires (likely due to EOF from the server). This is sub-optimal and can potentially cause a leak of the virNetClient object if the server were to not explicitly close the socket itself * src/remote/remote_driver.c: Explicitly close the client object when disconnecting * src/rpc/virnetclient.c, src/rpc/virnetclient.h: Add a virNetClientClose method --- src/remote/remote_driver.c | 2 ++ src/rpc/virnetclient.c | 22 +++++++++++++++++++++- src/rpc/virnetclient.h | 1 + 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index c2f8bbde06..6bae353c75 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -684,6 +684,7 @@ doRemoteOpen (virConnectPtr conn, free_qparam_set (vars); failed: + virNetClientClose(priv->client); virNetClientFree(priv->client); priv->client = NULL; @@ -834,6 +835,7 @@ doRemoteClose (virConnectPtr conn, struct private_data *priv) virNetTLSContextFree(priv->tls); priv->tls = NULL; + virNetClientClose(priv->client); virNetClientFree(priv->client); priv->client = NULL; virNetClientProgramFree(priv->remoteProgram); diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c index 27542a57ac..dfc4ed9494 100644 --- a/src/rpc/virnetclient.c +++ b/src/rpc/virnetclient.c @@ -255,7 +255,8 @@ void virNetClientFree(virNetClientPtr client) VIR_FREE(client->hostname); - virNetSocketRemoveIOCallback(client->sock); + if (client->sock) + virNetSocketRemoveIOCallback(client->sock); virNetSocketFree(client->sock); virNetTLSSessionFree(client->tls); #if HAVE_SASL @@ -268,6 +269,22 @@ void virNetClientFree(virNetClientPtr client) } +void virNetClientClose(virNetClientPtr client) +{ + virNetClientLock(client); + virNetSocketRemoveIOCallback(client->sock); + virNetSocketFree(client->sock); + client->sock = NULL; + virNetTLSSessionFree(client->tls); + client->tls = NULL; +#if HAVE_SASL + virNetSASLSessionFree(client->sasl); + client->sasl = NULL; +#endif + virNetClientUnlock(client); +} + + #if HAVE_SASL void virNetClientSetSASLSession(virNetClientPtr client, virNetSASLSessionPtr sasl) @@ -1118,6 +1135,9 @@ void virNetClientIncomingEvent(virNetSocketPtr sock, virNetClientLock(client); + if (!client->sock) + goto done; + /* This should be impossible, but it doesn't hurt to check */ if (client->waitDispatch) goto done; diff --git a/src/rpc/virnetclient.h b/src/rpc/virnetclient.h index 6acdf508a0..a0983bc734 100644 --- a/src/rpc/virnetclient.h +++ b/src/rpc/virnetclient.h @@ -81,5 +81,6 @@ const char *virNetClientRemoteAddrString(virNetClientPtr client); int virNetClientGetTLSKeySize(virNetClientPtr client); void virNetClientFree(virNetClientPtr client); +void virNetClientClose(virNetClientPtr client); #endif /* __VIR_NET_CLIENT_H__ */ -- GitLab