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 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel