[libvirt] [PATCH] Fix handling of stream EOF

Daniel P. Berrange berrange at redhat.com
Tue Oct 11 10:26:40 UTC 2011


From: "Daniel P. Berrange" <berrange at redhat.com>

Very occassionally the sequence of events from poll would result
in getting a HANGUP on its own, instead of a HANGUP+READABLE
at the same time. In the former case we would send back an error
event to the client, but never send the empty packet to indicate
EOF.
---
 daemon/stream.c |   40 ++++++++++++++++++++++++++++++++++++----
 1 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/daemon/stream.c b/daemon/stream.c
index 7df9952..50f8fd4 100644
--- a/daemon/stream.c
+++ b/daemon/stream.c
@@ -143,7 +143,8 @@ daemonStreamEvent(virStreamPtr st, int events, void *opaque)
 
     VIR_DEBUG("st=%p events=%d EOF=%d closed=%d", st, events, stream->recvEOF, stream->closed);
 
-    if (events & VIR_STREAM_EVENT_WRITABLE) {
+    if (!stream->closed &&
+        (events & VIR_STREAM_EVENT_WRITABLE)) {
         if (daemonStreamHandleWrite(client, stream) < 0) {
             daemonRemoveClientStream(client, stream);
             virNetServerClientClose(client);
@@ -151,9 +152,9 @@ daemonStreamEvent(virStreamPtr st, int events, void *opaque)
         }
     }
 
-    if (!stream->recvEOF &&
-        (events & (VIR_STREAM_EVENT_READABLE | VIR_STREAM_EVENT_HANGUP))) {
-        events = events & ~(VIR_STREAM_EVENT_READABLE | VIR_STREAM_EVENT_HANGUP);
+    if (!stream->closed && !stream->recvEOF &&
+        (events & (VIR_STREAM_EVENT_READABLE))) {
+        events = events & ~(VIR_STREAM_EVENT_READABLE);
         if (daemonStreamHandleRead(client, stream) < 0) {
             daemonRemoveClientStream(client, stream);
             virNetServerClientClose(client);
@@ -190,6 +191,37 @@ daemonStreamEvent(virStreamPtr st, int events, void *opaque)
         }
     }
 
+
+    /* If we got HANGUP, we need to only send an empty
+     * packet so the client sees an EOF and cleans up
+     */
+    if (!stream->closed && !stream->recvEOF &&
+        (events & VIR_STREAM_EVENT_HANGUP)) {
+        virNetMessagePtr msg;
+        events &= ~(VIR_STREAM_EVENT_HANGUP);
+        stream->tx = 0;
+        stream->recvEOF = 1;
+        if (!(msg = virNetMessageNew(false))) {
+            daemonRemoveClientStream(client, stream);
+            virNetServerClientClose(client);
+            goto cleanup;
+        }
+        msg->cb = daemonStreamMessageFinished;
+        msg->opaque = stream;
+        stream->refs++;
+        if (virNetServerProgramSendStreamData(remoteProgram,
+                                              client,
+                                              msg,
+                                              stream->procedure,
+                                              stream->serial,
+                                              "", 0) < 0) {
+            virNetMessageFree(msg);
+            daemonRemoveClientStream(client, stream);
+            virNetServerClientClose(client);
+            goto cleanup;
+        }
+    }
+
     if (!stream->closed &&
         (events & (VIR_STREAM_EVENT_ERROR | VIR_STREAM_EVENT_HANGUP))) {
         int ret;
-- 
1.7.6.4




More information about the libvir-list mailing list