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
This commit is contained in:
Daniel P. Berrange 2011-07-19 14:13:32 +01:00
parent 7ea2ef4ce8
commit e06c8ede42
3 changed files with 24 additions and 1 deletions

View File

@ -684,6 +684,7 @@ doRemoteOpen (virConnectPtr conn,
free_qparam_set (vars); free_qparam_set (vars);
failed: failed:
virNetClientClose(priv->client);
virNetClientFree(priv->client); virNetClientFree(priv->client);
priv->client = NULL; priv->client = NULL;
@ -834,6 +835,7 @@ doRemoteClose (virConnectPtr conn, struct private_data *priv)
virNetTLSContextFree(priv->tls); virNetTLSContextFree(priv->tls);
priv->tls = NULL; priv->tls = NULL;
virNetClientClose(priv->client);
virNetClientFree(priv->client); virNetClientFree(priv->client);
priv->client = NULL; priv->client = NULL;
virNetClientProgramFree(priv->remoteProgram); virNetClientProgramFree(priv->remoteProgram);

View File

@ -255,7 +255,8 @@ void virNetClientFree(virNetClientPtr client)
VIR_FREE(client->hostname); VIR_FREE(client->hostname);
virNetSocketRemoveIOCallback(client->sock); if (client->sock)
virNetSocketRemoveIOCallback(client->sock);
virNetSocketFree(client->sock); virNetSocketFree(client->sock);
virNetTLSSessionFree(client->tls); virNetTLSSessionFree(client->tls);
#if HAVE_SASL #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 #if HAVE_SASL
void virNetClientSetSASLSession(virNetClientPtr client, void virNetClientSetSASLSession(virNetClientPtr client,
virNetSASLSessionPtr sasl) virNetSASLSessionPtr sasl)
@ -1118,6 +1135,9 @@ void virNetClientIncomingEvent(virNetSocketPtr sock,
virNetClientLock(client); virNetClientLock(client);
if (!client->sock)
goto done;
/* This should be impossible, but it doesn't hurt to check */ /* This should be impossible, but it doesn't hurt to check */
if (client->waitDispatch) if (client->waitDispatch)
goto done; goto done;

View File

@ -81,5 +81,6 @@ const char *virNetClientRemoteAddrString(virNetClientPtr client);
int virNetClientGetTLSKeySize(virNetClientPtr client); int virNetClientGetTLSKeySize(virNetClientPtr client);
void virNetClientFree(virNetClientPtr client); void virNetClientFree(virNetClientPtr client);
void virNetClientClose(virNetClientPtr client);
#endif /* __VIR_NET_CLIENT_H__ */ #endif /* __VIR_NET_CLIENT_H__ */