libusb / libusb

A cross-platform library to access USB devices
https://libusb.info
GNU Lesser General Public License v2.1
5.14k stars 1.88k forks source link

All libusb objects must be released before libusb_exit is called: how to deal gracefully with closing a device while there are outstanding transfers? #703

Open ghost opened 4 years ago

ghost commented 4 years ago

libusb_cancel_transfer() can stop the transfer, but still calls the completion callback. There should be a way to stop them instantly (but still non-blocking), and allowing the application to do with the aborted libusb_transfer whatever it wants after the call, immediately, without having to wait for the callback.

This will make internal application logic simpler, which I think would benefit many users. I've wrote more about this in #700, but made a new issue, because the previous one was too hard to read.

diabolo38 commented 4 years ago

That is the way it is handled even in kernel space likely for good reasons The app shall consider the xfer belong to lib when submitted It is easy to handle a lock ans à flag in app data related to the xfer and analyse it in callback and Just do nothing is that case.

ghost commented 4 years ago

That usually means an app which wants to stop transfers immediately (without having to block or wait) has to add an indirection. I do it like this: have a chain of 2 callbacks, where libusb_transfer.callback is the first callback. The first callback checks whether the app "abandoned" this transfer, and only if not, calls the second callback. If the transfers was "abandoned", the app-managed device refcount is decreased, and if it has reached 0, usb_close is called. But that seems overly roundabout.

dickens commented 4 years ago

I am in favor of gracefully aborting all the outstanding transfers during libusb_close(), but the only safe thing to do is forget about the transfers entirely. Calling the callback, freeing the transfer buffer, and freeing the transfer itself are questionable at best in this scenario.

ghost commented 4 years ago

Getting more experience with using libusb, I think much of the evil issues is in libusb_transfer.callback. It seems to complicate a lot, both for users and libusb. A little bit of callback hell. But not sure how this could be improved.

mcuee commented 4 years ago

Maybe it is good to have some documentation improvement in this aspect.

zangetsudo commented 3 years ago

I am in favor of gracefully aborting all the outstanding transfers during libusb_close(), but the only safe thing to do is forget about the transfers entirely. Calling the callback, freeing the transfer buffer, and freeing the transfer itself are questionable at best in this scenario.

Im struggling with a issue that an endpoint is dead when a usb device does not responded to the endpoint with libusb recently, that ep is not getting recovered even if the device is unplugged & plugged. I'm looking forward to find the resolution even if it's Hack the code.

that will be grateful if anyone put patch(es) here....

Youw commented 3 years ago

There should be a way to stop them instantly (but still non-blocking), and allowing the application to do with the aborted libusb_transfer whatever it wants after the call, immediately

Is that even possible (even in theory)? You could easily try to stop a transfer right in the middle of the callback. To avoid issues in this case, you either explicitly wait for complitioon or libusb would have to add internal locks/checks whith wouldn't make things any easier for libusb itself, and libusb_cancel_transfer() becomes a blocking call.

mcuee commented 3 years ago
mcuee commented 3 years ago

So I have closed #297, #540 and #610 but keep #703. Edit: keeping #297 open as well.

mcuee commented 2 years ago

https://libusb.sourceforge.io/api-1.0/libusb_io.html

The synchronous interface
...
Additionally, there is no opportunity to cancel the transfer after the request has been submitted.
mcuee commented 1 year ago

Related issues: 1) https://github.com/libusb/libusb/issues/703 2) https://github.com/libusb/libusb/issues/182 3) https://github.com/libusb/libusb/issues/297 4) https://github.com/libusb/libusb/issues/540 5) https://github.com/libusb/libusb/issues/610

mcuee commented 1 year ago

I looked at the issue here and similar things were mentioned in the discussion. https://github.com/libusb/libusb/issues/1124

@hjelmn mentioned here.

Note also that ALL transfers MUST be freed before libusb_exit. This has always been the case but probably not well documented.

And here.

All libusb objects must be released before libusb_exit is called.

mcuee commented 1 year ago

Wiki updated. https://github.com/libusb/libusb/wiki/FAQ#user-content-What_are_the_differences_between_Synchronous_and_asynchronous_device_IO

Please take note that ALL transfers MUST be freed before libusb_exit() is called.

Please take note that ALL libusb objects MUST be released before libusb_exit() is called.

Please also take note that there is no way to cancel Synchronous transfer after the request has been submitted.