[Spice-devel] [PATCH spice-gtk 2/2] usb device widget: don't try to disconnect on failed connect

Jonathon Jongsma jjongsma at redhat.com
Thu Mar 24 20:29:24 UTC 2016


When you try to redirect a usb device to the guest and it fails, we
uncheck the checkbox for this device. This causes the 'clicked' signal
to be emitted, which causes us to try to disconnect the device (which is
not currently connected, since the connect operation failed).

When we try to disconnect an unconnected device, the device manager
leaks memory and gets left in an inconsistent state because we allocate
the task data, call _set_redirecting(self, TRUE) and then return early
with the following warning printed to the terminal:

(lt-spicy:4638): GSpice-CRITICAL **: spice_usbredir_channel_disconnect_device_async: assertion 'channel != NULL' failed

To avoid this, disable signal handlers for the checkbox 'clicked'
signal while we're changing the checkbox state in response to a
connection error. In addition, add an additional check to
spice_usb_device_manager_disconnect_device_async() to ensure that the
passed device is actually connected.
---
 src/usb-device-manager.c | 1 +
 src/usb-device-widget.c  | 6 ++++++
 2 files changed, 7 insertions(+)

diff --git a/src/usb-device-manager.c b/src/usb-device-manager.c
index cc95c68..9487f38 100644
--- a/src/usb-device-manager.c
+++ b/src/usb-device-manager.c
@@ -1827,6 +1827,7 @@ void spice_usb_device_manager_disconnect_device_async(SpiceUsbDeviceManager *sel
     g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self));
 
     g_return_if_fail(device != NULL);
+    g_return_if_fail(spice_usb_device_manager_is_device_connected(self, device);
 
     SPICE_DEBUG("disconnecting device %p", device);
 
diff --git a/src/usb-device-widget.c b/src/usb-device-widget.c
index 085f640..d3ea79a 100644
--- a/src/usb-device-widget.c
+++ b/src/usb-device-widget.c
@@ -478,6 +478,7 @@ static void _disconnect_cb(GObject *gobject, GAsyncResult *res, gpointer user_da
     connect_cb_data_free(data);
 }
 
+static void checkbox_clicked_cb(GtkWidget *check, gpointer user_data);
 static void connect_cb(GObject *gobject, GAsyncResult *res, gpointer user_data)
 {
     SpiceUsbDeviceManager *manager = SPICE_USB_DEVICE_MANAGER(gobject);
@@ -500,7 +501,12 @@ static void connect_cb(GObject *gobject, GAsyncResult *res, gpointer user_data)
         g_signal_emit(self, signals[CONNECT_FAILED], 0, device, err);
         g_error_free(err);
 
+        /* don't trigger a disconnect if connect failed */
+        g_signal_handlers_block_by_func(GTK_TOGGLE_BUTTON(data->check),
+                                        checkbox_clicked_cb, self);
         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->check), FALSE);
+        g_signal_handlers_unblock_by_func(GTK_TOGGLE_BUTTON(data->check),
+                                        checkbox_clicked_cb, self);
     }
 
     connect_cb_data_free(data);
-- 
2.4.3



More information about the Spice-devel mailing list