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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>
---
 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


[Index of Archives]     [Linux Virtualization]     [KVM Development]     [CentOS Virtualization]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]     [Video 4 Linux]

  Powered by Linux