[Spice-commits] server/stream-device.c

Frediano Ziglio fziglio at kemper.freedesktop.org
Fri Feb 16 22:19:05 UTC 2018


 server/stream-device.c |   29 ++++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)

New commits:
commit ebdda84dc145d7c6815a19d6b554bddabb6a0dfd
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Thu Jan 11 11:41:49 2018 +0000

    stream-device: Avoid device to get stuck if multiple messages are batched
    
    If messages are sent together by the agent the device is reading
    only part of the data. This cause Qemu to not poll for new data and
    stream_device_read_msg_from_dev won't be called again.
    This can cause a stall. To avoid this continue handling data
    after a full message was processed.
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/stream-device.c b/server/stream-device.c
index 4eaa959b..3a7cb306 100644
--- a/server/stream-device.c
+++ b/server/stream-device.c
@@ -71,16 +71,15 @@ static StreamMsgHandler handle_msg_format, handle_msg_data;
 static bool handle_msg_invalid(StreamDevice *dev, SpiceCharDeviceInstance *sin,
                                const char *error_msg) SPICE_GNUC_WARN_UNUSED_RESULT;
 
-static RedPipeItem *
-stream_device_read_msg_from_dev(RedCharDevice *self, SpiceCharDeviceInstance *sin)
+static bool
+stream_device_partial_read(StreamDevice *dev, SpiceCharDeviceInstance *sin)
 {
-    StreamDevice *dev = STREAM_DEVICE(self);
     SpiceCharDeviceInterface *sif;
     int n;
     bool handled = false;
 
     if (dev->has_error || dev->flow_stopped || !dev->stream_channel) {
-        return NULL;
+        return false;
     }
 
     sif = spice_char_device_get_interface(sin);
@@ -89,7 +88,7 @@ stream_device_read_msg_from_dev(RedCharDevice *self, SpiceCharDeviceInstance *si
     while (dev->hdr_pos < sizeof(dev->hdr)) {
         n = sif->read(sin, (uint8_t *) &dev->hdr + dev->hdr_pos, sizeof(dev->hdr) - dev->hdr_pos);
         if (n <= 0) {
-            return NULL;
+            return false;
         }
         dev->hdr_pos += n;
         if (dev->hdr_pos >= sizeof(dev->hdr)) {
@@ -123,6 +122,26 @@ stream_device_read_msg_from_dev(RedCharDevice *self, SpiceCharDeviceInstance *si
         dev->hdr_pos = 0;
     }
 
+    if (handled || dev->has_error) {
+        // Qemu put the device on blocking state if we don't read all data
+        // so schedule another read.
+        // We arrive here if we processed that entire message or we
+        // got an error, try to read another message or discard the
+        // wrong data
+        return true;
+    }
+
+    return false;
+}
+
+static RedPipeItem *
+stream_device_read_msg_from_dev(RedCharDevice *self, SpiceCharDeviceInstance *sin)
+{
+    StreamDevice *dev = STREAM_DEVICE(self);
+
+    while (stream_device_partial_read(dev, sin)) {
+        continue;
+    }
     return NULL;
 }
 


More information about the Spice-commits mailing list