[Spice-devel] [PATCH spice-server v5 1/8] stream-device: Avoid device to get stuck if multiple messages are batched

Jonathon Jongsma jjongsma at redhat.com
Fri Feb 16 21:47:52 UTC 2018


On Tue, 2018-02-13 at 15:54 +0000, Frediano Ziglio wrote:
> 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>
> ---
>  server/stream-device.c | 29 ++++++++++++++++++++++++-----
>  1 file changed, 24 insertions(+), 5 deletions(-)
> 
> 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;
>  }
>  


Thanks. I prefer this approach instead of calling
red_char_device_wakeup(). The name stream_device_partial_read() is OK,
but it's not great. It is really reading up until the end of the next
message *or* until there is no more data to read. I thought about
stream_device_read_to_end_of_message(), but that's not very nice
either. I can't think of a great name.

Acked-by: Jonathon Jongsma <jjongsma at redhat.com>


More information about the Spice-devel mailing list