You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Assume you have a multi-threaded application that has a lot of in-flight async. transfers (such as continuous data transfer from a device). If you want to safely close the USB device, you need to:
keep a list of all transfers
call libusb_cancel_transfer() on each of it
wait until their completion callbacks have been called
call libusb_close
I think this is too complex. I'd really just want to be able to stop transfers and/or close a device in a non-blocking and instant way. I'd prefer something like this:
being able to instanly stop libusb_transfers and make libusb completely forget about them
being able to just close libusb_device_handles without having to worry about ongoing transfers
maybe provide an event queue to signal libusb_transfer completion instead of a tricky callback
Now, the first suggestion would probably be to set the LIBUSB_TRANSFER_FREE_BUFFER and LIBUSB_TRANSFER_FREE_TRANSFER flags on each transfer. But you'd still need to clear the completion callbacks (see below), and it doesn't seem to solve this problem anyway (other than fixing memory leaks).
libusb_cancel_transfer() is not enough either. It will still call the completion callback. The function doesn't even tell you whether a callback will be called. (It can return LIBUSB_ERROR_NOT_FOUND when the transfer was already canceled, and the completion callback is still to be called.)
Can you safely set libusb_transfer.callback to NULL? The user has no control over when libusb reads this field. Do you need to lock via libusb_lock_events()? Do you need to do it on whichever thread you call libusb_handle_events()? Or is it not possible? In general, I'm rather confused about in which context completion callbacks can be called.
And with all that, you still need to know when you can call libusb_close(). If you just "orphan" all transfers (like described above, and for the sake of your application logic), you don't know when the transfers actually complete, so you can close the device.
Can you just call libusb_close() with transfers still ongoing? It seems it somehow synchronously cancels transfers, prints an ugly warning, and calls the completion callbacks synchronously. But judging from past issues, this is more like a hack to make API user errors less fatal.
Note that this doesn't just affect closing devices. If it's some sort of multi-function device, the application may have multiple subsystems (using different USB endpoints) that you may want to start/stop independently without closing the device. So if you want to stop transfers instantly for simplicity, you're still... troubled.
It's also possible that I'm overthinking this, and there's a way to handle this correctly. I've spent a lot time thinking about this though, and I've wrote my own 500 line helper which "garbage collects" libusb_transfers (and optionally libusb_device_handles) once nothing needs/wants them anymore. Judging by how many vaguely similar issues there are on this repo (where similar things were discussed), I assume this is a common problem though.
The text was updated successfully, but these errors were encountered:
Assume you have a multi-threaded application that has a lot of in-flight async. transfers (such as continuous data transfer from a device). If you want to safely close the USB device, you need to:
I think this is too complex. I'd really just want to be able to stop transfers and/or close a device in a non-blocking and instant way. I'd prefer something like this:
Now, the first suggestion would probably be to set the LIBUSB_TRANSFER_FREE_BUFFER and LIBUSB_TRANSFER_FREE_TRANSFER flags on each transfer. But you'd still need to clear the completion callbacks (see below), and it doesn't seem to solve this problem anyway (other than fixing memory leaks).
libusb_cancel_transfer()
is not enough either. It will still call the completion callback. The function doesn't even tell you whether a callback will be called. (It can returnLIBUSB_ERROR_NOT_FOUND
when the transfer was already canceled, and the completion callback is still to be called.)Can you safely set
libusb_transfer.callback
toNULL
? The user has no control over when libusb reads this field. Do you need to lock vialibusb_lock_events()
? Do you need to do it on whichever thread you calllibusb_handle_events()
? Or is it not possible? In general, I'm rather confused about in which context completion callbacks can be called.And with all that, you still need to know when you can call
libusb_close()
. If you just "orphan" all transfers (like described above, and for the sake of your application logic), you don't know when the transfers actually complete, so you can close the device.Can you just call
libusb_close()
with transfers still ongoing? It seems it somehow synchronously cancels transfers, prints an ugly warning, and calls the completion callbacks synchronously. But judging from past issues, this is more like a hack to make API user errors less fatal.Note that this doesn't just affect closing devices. If it's some sort of multi-function device, the application may have multiple subsystems (using different USB endpoints) that you may want to start/stop independently without closing the device. So if you want to stop transfers instantly for simplicity, you're still... troubled.
It's also possible that I'm overthinking this, and there's a way to handle this correctly. I've spent a lot time thinking about this though, and I've wrote my own 500 line helper which "garbage collects" libusb_transfers (and optionally libusb_device_handles) once nothing needs/wants them anymore. Judging by how many vaguely similar issues there are on this repo (where similar things were discussed), I assume this is a common problem though.
The text was updated successfully, but these errors were encountered: