[virt-tools-list] [PATCH 08/11] session-spice: Delay the disconnected signal till all channels are closed

Hans de Goede hdegoede at redhat.com
Sun Mar 4 19:05:59 UTC 2012


Before this patch session-spice would emit the disconnected signal as soon
as the main channel is closed, but other channels may still be open at
that time and raising the disconnected signal usally leads to the app class
calling gtk_main_quit, at which point the other channels never get properly
finalized (as there co-routines still hold a reference to them).

This is esp. bad for usbredir channels as these re-attach the kernel driver
for redirected devices when finalized. So exiting without properly finalizing
them leads to the formerly redirected devices not being usuable until the
driver is manually reloaded or the device is unplugged and re-plugged
(the kernel does not automatically re-bind kernel drivers when userspace
 closes a usbfs node).

This patch fixes this by delaying the emitting of the disconnect signal
until the last channel has been destroyed.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 src/virt-viewer-session-spice.c |   17 +++++++++++++----
 1 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/src/virt-viewer-session-spice.c b/src/virt-viewer-session-spice.c
index 3250abd..a4b3a1f 100644
--- a/src/virt-viewer-session-spice.c
+++ b/src/virt-viewer-session-spice.c
@@ -48,6 +48,7 @@ struct _VirtViewerSessionSpicePrivate {
     SpiceGtkSession *gtk_session;
     SpiceMainChannel *main_channel;
     SpiceAudio *audio;
+    int channel_count;
 };
 
 #define VIRT_VIEWER_SESSION_SPICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), VIRT_VIEWER_TYPE_SESSION_SPICE, VirtViewerSessionSpicePrivate))
@@ -301,7 +302,10 @@ virt_viewer_session_spice_main_channel_event(SpiceChannel *channel G_GNUC_UNUSED
         break;
     case SPICE_CHANNEL_CLOSED:
         DEBUG_LOG("main channel: closed");
-        g_signal_emit_by_name(session, "session-disconnected");
+        /* Ensure the other channels get closed too */
+        virt_viewer_session_clear_displays(session);
+        if (self->priv->session)
+            spice_session_disconnect(self->priv->session);
         break;
     case SPICE_CHANNEL_ERROR_CONNECT:
         DEBUG_LOG("main channel: failed to connect");
@@ -436,10 +440,11 @@ virt_viewer_session_spice_channel_new(SpiceSession *s,
 
     if (SPICE_IS_PLAYBACK_CHANNEL(channel)) {
         DEBUG_LOG("new audio channel");
-        if (self->priv->audio != NULL)
-            return;
-        self->priv->audio = spice_audio_new(s, NULL, NULL);
+        if (self->priv->audio == NULL)
+            self->priv->audio = spice_audio_new(s, NULL, NULL);
     }
+
+    self->priv->channel_count++;
 }
 
 static void
@@ -468,6 +473,10 @@ virt_viewer_session_spice_channel_destroy(G_GNUC_UNUSED SpiceSession *s,
         g_object_unref(self->priv->audio);
         self->priv->audio = NULL;
     }
+
+    self->priv->channel_count--;
+    if (self->priv->channel_count == 0)
+        g_signal_emit_by_name(self, "session-disconnected");
 }
 
 VirtViewerSession *
-- 
1.7.7.6




More information about the virt-tools-list mailing list