diff options
author | Daniel P. Berrange <berrange@redhat.com> | 2011-08-14 15:44:45 -0700 |
---|---|---|
committer | Daniel P. Berrange <berrange@redhat.com> | 2011-08-16 14:38:11 -0700 |
commit | f682c2530869b6f7c290537a68808e536c6a72c7 (patch) | |
tree | b465bbebc34e4bb89f7c907126ea827125ca8aba /daemon/stream.c | |
parent | Ensure stream is aborted when exiting console (diff) | |
download | libvirt-f682c2530869b6f7c290537a68808e536c6a72c7.tar.gz libvirt-f682c2530869b6f7c290537a68808e536c6a72c7.tar.bz2 libvirt-f682c2530869b6f7c290537a68808e536c6a72c7.zip |
Ensure client streams are closed when marking a client for close
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
* daemon/stream.c, daemon/stream.h: Add API for releasing
all streams
* src/rpc/virnetserverclient.c, src/rpc/virnetserverclient.h:
Allow registration of a hook to trigger when closing client
Diffstat (limited to 'daemon/stream.c')
-rw-r--r-- | daemon/stream.c | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/daemon/stream.c b/daemon/stream.c index 4a8f1eed9..7dd9ae770 100644 --- a/daemon/stream.c +++ b/daemon/stream.c @@ -334,13 +334,17 @@ int daemonFreeClientStream(virNetServerClientPtr client, msg = stream->rx; while (msg) { virNetMessagePtr tmp = msg->next; - /* Send a dummy reply to free up 'msg' & unblock client rx */ - memset(msg, 0, sizeof(*msg)); - msg->header.type = VIR_NET_REPLY; - if (virNetServerClientSendMessage(client, msg) < 0) { - virNetServerClientImmediateClose(client); + if (client) { + /* Send a dummy reply to free up 'msg' & unblock client rx */ + memset(msg, 0, sizeof(*msg)); + msg->header.type = VIR_NET_REPLY; + if (virNetServerClientSendMessage(client, msg) < 0) { + virNetServerClientImmediateClose(client); + virNetMessageFree(msg); + ret = -1; + } + } else { virNetMessageFree(msg); - ret = -1; } msg = tmp; } @@ -441,6 +445,28 @@ daemonRemoveClientStream(virNetServerClientPtr client, } +void +daemonRemoveAllClientStreams(daemonClientStream *stream) +{ + daemonClientStream *tmp; + + VIR_DEBUG("stream=%p", stream); + + while (stream) { + tmp = stream->next; + + if (!stream->closed) { + virStreamEventRemoveCallback(stream->st); + virStreamAbort(stream->st); + } + + daemonFreeClientStream(NULL, stream); + + VIR_DEBUG("next stream=%p", tmp); + stream = tmp; + } +} + /* * Returns: * -1 if fatal error occurred |