aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel P. Berrange <berrange@redhat.com>2011-08-14 15:44:45 -0700
committerDaniel P. Berrange <berrange@redhat.com>2011-08-16 14:38:11 -0700
commitf682c2530869b6f7c290537a68808e536c6a72c7 (patch)
treeb465bbebc34e4bb89f7c907126ea827125ca8aba /daemon/stream.c
parentEnsure stream is aborted when exiting console (diff)
downloadlibvirt-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.c38
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