[Spice-commits] server/red-channel-client.c

Christophe Fergau teuf at kemper.freedesktop.org
Tue Oct 10 13:50:06 UTC 2017

 server/red-channel-client.c |    6 ++++++
 1 file changed, 6 insertions(+)

New commits:
commit 657a1d92e8844c0b931e40e035e4f2b97f087489
Author: Christophe Fergeau <cfergeau at redhat.com>
Date:   Thu Oct 5 13:53:49 2017 +0200

    dcc: Fix seamless migration
    Since commit ef4b1bdb "red-channel-client: Prevent too tight loop
    waiting for ACKs", after seamless migration, the display is no longer
    updated on the client-side, even though the VM is functional (responds
    to keyboard input, reconnecting the client restores the display
    functionality, ...).
    This is mainly caused because after migration,
    red_channel_client_waiting_for_ack() will be true until
    red_channel_client_ack_zero_messages_window() is called.
    What happens is the following:
    The dcc is created, and dcc_start() pushes a RED_PIPE_ITEM_TYPE_SET_ACK
    This calls prepare_pipe_add(), which will enable write event on the dcc
    watch. red_channel_client_event() will be called, which will trigger a
    red_channel_client_push(). Since red_channel_client_waiting_for_ack()
    returns true, we won't get any item to push, and (because of commit
    ef4b1bdb), we will disable write notifications on the watch.
    At this point, rcc->priv->pipe is no longer empty, so prepare_pipe_add()
    is not going to reenable the write notifications.
    Then red_channel_client_ack_zero_messages_window() is finally called as
    part of dcc_handle_migrate_data(), so from this point on,
    red_channel_client_waiting_for_ack() is no longer true.
    However, nothing ever reenables WRITE events, nor empties
    rcc->priv->pipe, so nothing ever gets pushed, causing no display updates
    at all after a migration, even if the VM is functional (input, ...)
    apart from that.
    This commit reenables WRITE events in
    red_channel_client_ack_zero_messages_window() if we were waiting for
    Signed-off-by: Christophe Fergeau <cfergeau at redhat.com>

diff --git a/server/red-channel-client.c b/server/red-channel-client.c
index a8c6f33f..a707dbcb 100644
--- a/server/red-channel-client.c
+++ b/server/red-channel-client.c
@@ -1327,6 +1327,10 @@ void red_channel_client_push(RedChannelClient *rcc)
     while ((pipe_item = red_channel_client_pipe_item_get(rcc))) {
         red_channel_client_send_item(rcc, pipe_item);
+    /* prepare_pipe_add() will reenable WRITE events when the rcc->priv->pipe is empty
+     * red_channel_client_ack_zero_messages_window() will reenable WRITE events
+     * if we were waiting for acks to be received
+     */
     if ((red_channel_client_no_item_being_sent(rcc) && g_queue_is_empty(&rcc->priv->pipe)) ||
         red_channel_client_waiting_for_ack(rcc)) {
         red_channel_client_watch_update_mask(rcc, SPICE_WATCH_EVENT_READ);
@@ -1677,6 +1681,8 @@ static void red_channel_client_pipe_clear(RedChannelClient *rcc)
 void red_channel_client_ack_zero_messages_window(RedChannelClient *rcc)
+    red_channel_client_watch_update_mask(rcc,
+                                         SPICE_WATCH_EVENT_READ|SPICE_WATCH_EVENT_WRITE);
     rcc->priv->ack_data.messages_window = 0;

More information about the Spice-commits mailing list