[Spice-devel] [spice-gtk 3/3] usb-device-manager: Fix USB event thread leak
Christophe Fergeau
cfergeau at redhat.com
Wed Jun 29 15:42:15 UTC 2016
When using USB redirection, it's fairly easy to leak the thread handling
USB events, which will eventually cause problems in long lived apps.
In particular, in virt-manager, one can:
- start a VM
- connect to it with SPICE
- open the USB redirection window
- redirect a device
- close the SPICE window
-> the SpiceUsbDeviceManager instance will be destroyed (including the
USB context it owns), but the associated event thread will keep running.
Since it's running a loop blocking on libusb_handle_events(priv->context),
the loop will eventually try to use the USB context we just destroyed
causing a crash.
We can get in this situation when redirecting a USB device because we
will call spice_usb_device_manager_start_event_listening() in
spice_usbredir_channel_open_device(). The matching
spice_usb_device_manager_stop_event_listening() call is supposed to
happen in spice_usbredir_channel_disconnect_device(), however by the
time it's called in the scenario described above, the session associated
with the channel will already have been set to NULL in
spice_session_channel_destroy().
Since the USB event thread has to be stopped when we destroy the
associated SpiceUsbDeviceManager, spice_usb_device_manager_dispose()
should force event_thread_run to FALSE rather than calling
spice_usb_device_manager_stop_event_listening() which will only set it
to FALSE if this was the only user of the event thread.
This fixes https://bugzilla.redhat.com/show_bug.cgi?id=1217202
(virt-manager) and most
likely https://bugzilla.redhat.com/show_bug.cgi?id=1337007 (gnome-boxes)
as well.
---
src/usb-device-manager.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/usb-device-manager.c b/src/usb-device-manager.c
index 1912b62..2b10be2 100644
--- a/src/usb-device-manager.c
+++ b/src/usb-device-manager.c
@@ -374,7 +374,9 @@ static void spice_usb_device_manager_dispose(GObject *gobject)
#ifdef USE_LIBUSB_HOTPLUG
if (priv->hp_handle) {
- spice_usb_device_manager_stop_event_listening(self);
+ /* Force termination of the event thread even if there were some mismatched
+ * spice_usb_device_manager_{start,stop}_event_listening calls */
+ g_atomic_int_set(&priv->event_thread_run, FALSE);
/* This also wakes up the libusb_handle_events() in the event_thread */
libusb_hotplug_deregister_callback(priv->context, priv->hp_handle);
priv->hp_handle = 0;
--
2.7.4
More information about the Spice-devel
mailing list