]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Fix handling of stream EOF
authorDaniel P. Berrange <berrange@redhat.com>
Fri, 7 Oct 2011 16:38:59 +0000 (17:38 +0100)
committerCole Robinson <crobinso@redhat.com>
Thu, 14 Jun 2012 21:32:37 +0000 (17:32 -0400)
Very occasionally 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.
(cherry picked from commit 1d46b2e900498a3f389fcbb89fc7b27d22f36d4a)

daemon/stream.c

index e3214c2f5704d791a3e7b2d7f372c3053299d959..29402041416a01753b66f7d3adee36783755a4ee 100644 (file)
@@ -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;