> > > #2 0x00007f23e8bfbb13 in libusb_handle_events_timeout_completed () at > > > /lib64/libusb-1.0.so.0 > > > #3 0x000055e09854b7da in usb_host_abort_xfers (s=0x55e09b036dd0) at > > > hw/usb/host-libusb.c:963
> > Hmm, does reverting 76d0a9362c6a6a7d88aa18c84c4186c9107ecaef change > > behavior? > > Yes it does. Reverting that patch fixes the problem, no hang and device > reconnects without problem. Hmm. Looks like an libusb bug to me, it seems to not call the completion callback for the canceled transfers (which it should do according to the docs), so qemu waits for this to happen forever. We can certainly add a limit here (see below), question is how to handle the canceled but not completed transfers then. I suspect we have to leak them to make sure we don't get use-after-free access from libusb ... cheers, Gerd diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index e28441379d99..4c3b5b140d9d 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -944,30 +944,45 @@ fail: libusb_close(s->dh); s->dh = NULL; s->dev = NULL; } return -1; } static void usb_host_abort_xfers(USBHostDevice *s) { USBHostRequest *r, *rtmp; + int limit = 100; QTAILQ_FOREACH_SAFE(r, &s->requests, next, rtmp) { usb_host_req_abort(r); } while (QTAILQ_FIRST(&s->requests) != NULL) { struct timeval tv; memset(&tv, 0, sizeof(tv)); tv.tv_usec = 2500; libusb_handle_events_timeout(ctx, &tv); + if (--limit == 0) { + /* + * Don't wait forever for libusb calling the complete + * callback (which will unlink and free the request). + * + * Leaking memory here, to make sure libusb will not + * access memory which we have released already. + */ + QTAILQ_FOREACH_SAFE(r, &s->requests, next, rtmp) { + fprintf(stderr, "%s: leaking usb request %p\n", __func__, r); + QTAILQ_REMOVE(&s->requests, r, next); + } + return; + } } } static int usb_host_close(USBHostDevice *s) { USBDevice *udev = USB_DEVICE(s); if (s->dh == NULL) { return -1; }