a089ec2f5f
Resolves: rhbz#1217202 (virt-manager) May help with rhbz#1338042 (gnome-boxes)
49 lines
2.2 KiB
Diff
49 lines
2.2 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Christophe Fergeau <cfergeau@redhat.com>
|
|
Date: Wed, 29 Jun 2016 16:57:36 +0200
|
|
Subject: [PATCH] usb-device-manager: Avoid USB event thread leak
|
|
|
|
This is a follow-up of the previous commit ('usb-channel: Really stop
|
|
listening for USB events on disconnection').
|
|
|
|
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 even if
|
|
spice_usb_device_manager_stop_event_listening() was not enough. When
|
|
this happens, this means that there is a bug in the internal users of
|
|
spice_usb_device_manager_start_event_listening(), but with this change,
|
|
we'll at least warn about it, and avoid a thread leak/potential future
|
|
crash.
|
|
---
|
|
src/usb-device-manager.c | 12 +++++++++++-
|
|
1 file changed, 11 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/usb-device-manager.c b/src/usb-device-manager.c
|
|
index 808ec6c..53505fa 100644
|
|
--- a/src/usb-device-manager.c
|
|
+++ b/src/usb-device-manager.c
|
|
@@ -375,12 +375,22 @@ 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);
|
|
+ if (g_atomic_int_get(&priv->event_thread_run)) {
|
|
+ /* Force termination of the event thread even if there were some
|
|
+ * mismatched spice_usb_device_manager_{start,stop}_event_listening
|
|
+ * calls. Otherwise, the usb event thread will be leaked, and will
|
|
+ * try to use the libusb context we destroy in finalize(), which would
|
|
+ * cause a crash */
|
|
+ g_warn_if_reached();
|
|
+ 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;
|
|
}
|
|
#endif
|
|
- if (priv->event_thread && !g_atomic_int_get(&priv->event_thread_run)) {
|
|
+ if (priv->event_thread) {
|
|
+ g_warn_if_fail(g_atomic_int_get(&priv->event_thread_run) == FALSE);
|
|
g_thread_join(priv->event_thread);
|
|
priv->event_thread = NULL;
|
|
}
|