Summary: | libusb_cancel_transfer() does NOT cancel a transfer after the USB device is removed | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Product: | Base System | Reporter: | Ludovic Rousseau <ludovic.rousseau+freebsd> | ||||||||
Component: | usb | Assignee: | Hans Petter Selasky <hselasky> | ||||||||
Status: | Closed FIXED | ||||||||||
Severity: | Affects Some People | CC: | b.altendorf, hselasky | ||||||||
Priority: | --- | ||||||||||
Version: | 10.4-STABLE | ||||||||||
Hardware: | Any | ||||||||||
OS: | Any | ||||||||||
Attachments: |
|
Description
Ludovic Rousseau
2018-09-01 15:20:28 UTC
Hi, I sounds like you have closed the libusb handle before trying to cancel the USB transfers. What libusb_xxx() calls are you making before the libusb_cancel_transfer() fails? Sounds like a race. --HPS Or that the LibUSB v1.0 transfer was never actually setup and submitted? I added logs in my code. When I start the transfer I have: 00000006 ccid_usb.c:1329:InterruptRead() uxfer->dev_handle: 0x28c0c9c0 When I cancel the transfer I have: 00000004 ccid_usb.c:1399:InterruptStop() uxfer->dev_handle: 0x28c0c9c0 So the problem is not at line 1501 as I initially mentioned. https://github.com/freebsd/freebsd/blob/master/lib/libusb/libusb10.c#L1501 No, the handle has not been closed. libusb_close() is called _after_ the transfer is cancelled. Yes, the transfer has started. At least I get no error when I start it. Yes, I get data from the interrupt pipe when a smart card is inserted or removed. So the USB communication does work with the interrupt pipe. Yes, I can cancel the transfer when the USB device is present. The program does that when Ctrl-C is used to stop it. The problem happens when the USB device is no more connected. I added a call to libusb_set_debug(ctx, LIBUSB_LOG_LEVEL_DEBUG); in my code but I don't see more debug. I see that libusb uses DPRINTF(). How can I get the generated log messages? >I added a call to libusb_set_debug(ctx, LIBUSB_LOG_LEVEL_DEBUG); in my code but
>I don't see more debug.
>I see that libusb uses DPRINTF(). How can I get the generated log messages?
LIBUSB_DEBUG_NO=0,
LIBUSB_DEBUG_FUNCTION=1,
LIBUSB_DEBUG_TRANSFER=2,
Try using one of the above arguments when calling libusb_set_debug().
--HPS
I get log message when using libusb_set_debug(ctx, LIBUSB_DEBUG_FUNCTION); After I remove the device I get: LIBUSB_FUNCTION: libusb10_handle_events_sub enter 04338703 hotplug_libusb.c:626:HPRemoveHotPluggable() Removing USB device[0]: 0:2:0 00000009 readerfactory.c:610:RFRemoveReader() UnrefReader() count was: 1 00000003 eventhandler.c:175:EHDestroyEventHandler() Stomping thread. 00000005 ifdhandler.c:381:IFDHGetCapabilities() tag: 0xFB1, usb:2406/6407:libusb-1.0:0:2:0 (lun: 0) 00000003 ifdhandler.c:381:IFDHGetCapabilities() tag: 0xFB2, usb:2406/6407:libusb-1.0:0:2:0 (lun: 0) 00000004 eventhandler.c:200:EHDestroyEventHandler() Request stopping of polling thread 00000004 ifdhandler.c:346:IFDHStopPolling() usb:2406/6407:libusb-1.0:0:2:0 (lun: 0) 00000003 ccid_usb.c:1399:InterruptStop() uxfer->dev_handle: 0x28c0c9c0 LIBUSB_FUNCTION: libusb_cancel_transfer enter LIBUSB_FUNCTION: libusb_cancel_transfer leave 00000010 ccid_usb.c:1403:InterruptStop() libusb_cancel_transfer failed: LIBUSB_ERROR_NOT_FOUND I guess I now have to instrument libusb to get more logs. How can I rebuild libusb? I added more logs in libusb, rebuilt and installed. The problem is that I get in the "not started" case: https://github.com/freebsd/freebsd/blob/master/lib/libusb/libusb10.c#L1546 I logged all the fields used in the if/else cases: LIBUSB_FUNCTION: libusb_cancel_transfer enter LIBUSB_FUNCTION: state: 1 LIBUSB_FUNCTION: entry.tqe_prev: 0x0 LIBUSB_FUNCTION: sxfer: 0x29007060 LIBUSB_FUNCTION: pxfer0: 0x28c2f348 LIBUSB_FUNCTION: pxfer1: 0x28c2f384 LIBUSB_FUNCTION: libusb20_tr_get_priv_sc1(pxfer0): 0x0 LIBUSB_FUNCTION: libusb20_tr_get_priv_sc1(pxfer1): 0x0 LIBUSB_FUNCTION: libusb_cancel_transfer leave I don't know yet why libusb20_tr_get_priv_sc1() returns NULL. What else should I do? The private pointer is set when you submit a transfer. It basically means that the transfer was never submitted. See: libusb20_tr_set_priv_sc1(pxfer0, sxfer); Do you have a printout for error codes in the completion function? --HPS Try to collect logs using LIBUSB_DEBUG_TRANSFER aswell. When the USB device is removed libusb10_handle_events_sub() will call libusb10_cancel_all_transfer() at https://github.com/freebsd/freebsd/blob/master/lib/libusb/libusb10_io.c#L170 libusb10_cancel_all_transfer() will then call libusb20_tr_close() at https://github.com/freebsd/freebsd/blob/master/lib/libusb/libusb10.c#L1570 libusb20_tr_close() will then reset the variable fields at https://github.com/freebsd/freebsd/blob/master/lib/libusb/libusb20.c#L142 So when libusb_cancel_transfer() is called by my code the fields priv_sc0 and priv_sc1 are already reset to 0 and libusb_cancel_transfer() returns LIBUSB_ERROR_NOT_FOUND in https://github.com/freebsd/freebsd/blob/master/lib/libusb/libusb10.c#L1547 I can test any patch you propose to fix the issue. I have no problem with libusb_cancel_transfer() failing with the error LIBUSB_ERROR_NOT_FOUND. I can handle that. My problem is that libusb_handle_events_completed() (in another thread) does NOT return. On device removal it looks like the USB transfers are cancelled at the libusb internal level but not for libusb_handle_events_completed(). > My problem is that libusb_handle_events_completed() (in another thread) does NOT return.
I see.
Are you aware about libusb_handle_events_timeout_completed()?
From what I can see "libusb_close()" will write a byte on the control pipe which should wakeup libusb_handle_events_completed(). Are you waiting for this wakeup before calling libusb_close() or after?
--HPS
There also exist: libusb_handle_events_completed(), with the specific purpose to set the completed=1, when you want to force the wait loop to exit. This should be done before calling libusb_close(). Refer to the LibUSB manual pages on the internet for how to use. Created attachment 196888 [details]
LibUSB patch
Does this patch help?
My analysis is the following that FreeBSD lacks a libusb transfer completion event when a USB device is detached. This state can be detected using libusb_check_connected(), which returns non-zero when the USB device has been detached. The problem can be worked around by signalling the worker thread from the close function, which then makes poll()/libusb_handle_events_completed() return and then you simply do: #ifdef __FreeBSD__ if (libusb_check_connected(udevh)) { libusb_free_transfer(transfer); return IFD_COMMUNICATION_ERROR; } #endif Signalling the worker thread results in libusb_handle_events_completed() returning non-zero: Something like this: err = libusb_handle_events_completed(); #ifdef __FreeBSD__ if (err != 0) { if (libusb_check_connected(udevh)) { libusb_cancel_transfer(transfer); libusb_free_transfer(transfer); return IFD_COMMUNICATION_ERROR; } } #endif (In reply to Hans Petter Selasky from comment #13) No. The patch does not help. I added a log so see if the line "process_all = 1;" is executed and the line is executed only once at near the beginning. $ sudo LIBCCID_ifdLogLevel=0x000F ./pcscd --foreground --debug --apdu --color 00000000 debuglog.c:289:DebugLogSetLevel() debug level=debug 00000022 debuglog.c:310:DebugLogSetCategory() Debug options: APDU 00000006 pcscdaemon.c:352:main() Force colored logs 00000134 configfile.l:361:DBGetReaderList() Parsing conf file: /usr/local/etc/reader.conf.d 00000024 pcscdaemon.c:662:main() pcsc-lite 1.8.23 daemon ready. 00001928 hotplug_libusb.c:440:HPEstablishUSBNotifications() Driver ifd-ccid.bundle does not support IFD_GENERATE_HOTPLUG. Using active polling instead. 00000013 hotplug_libusb.c:449:HPEstablishUSBNotifications() Polling forced every 1 second(s) 03079650 hotplug_libusb.c:536:HPAddHotPluggable() Adding USB device: 0:2:0 00000026 readerfactory.c:1075:RFInitializeReader() Attempting startup of Inside Secure AT90SCR200 00 00 using /usr/local/lib/pcsc/drivers/ifd-ccid.bundle/Contents/FreeBSD/libccid.so 00000089 readerfactory.c:950:RFBindFunctions() Loading IFD Handler 3.0 00000028 ifdhandler.c:1961:init_driver() Driver version: 1.4.29 00000787 ifdhandler.c:1978:init_driver() LogLevel: 0x0003 00000009 ifdhandler.c:1989:init_driver() DriverOptions: 0x0000 00000262 ifdhandler.c:2002:init_driver() LogLevel from LIBCCID_ifdLogLevel: 0x000F 00000007 ifdhandler.c:110:CreateChannelByNameOrChannel() Lun: 0, device: usb:2406/6407:libusb-1.0:0:2:0 00000011 ccid_usb.c:237:OpenUSBByName() Reader index: 0, Device: usb:2406/6407:libusb-1.0:0:2:0 00000021 ccid_usb.c:282:OpenUSBByName() interface_number: 0 00000005 ccid_usb.c:284:OpenUSBByName() usb bus/device: 0/2 00000005 ccid_usb.c:302:OpenUSBByName() Using: /usr/local/lib/pcsc/drivers//ifd-ccid.bundle/Contents/Info.plist 00000599 ccid_usb.c:320:OpenUSBByName() ifdManufacturerString: Ludovic Rousseau (ludovic.rousseau@free.fr) 00000007 ccid_usb.c:321:OpenUSBByName() ifdProductString: Generic CCID driver 00000007 ccid_usb.c:322:OpenUSBByName() Copyright: This driver is protected by terms of the GNU Lesser General Public License version 2.1, or (at your option) any later version. 00000214 ccid_usb.c:407:OpenUSBByName() Try device: 0/2 00000008 ccid_usb.c:417:OpenUSBByName() vid/pid : 2406/6407 00000004 ccid_usb.c:484:OpenUSBByName() Checking device: 0/2 00000005 ccid_usb.c:555:OpenUSBByName() Trying to open USB bus/device: 0/2 00000059 ccid_usb.c:661:OpenUSBByName() Found Vendor/Product: 2406/6407 (Inside Secure AT90SCR200) 00000006 ccid_usb.c:663:OpenUSBByName() Using USB bus/device: 0/2 00000005 ccid_usb.c:723:OpenUSBByName() bNumDataRatesSupported is 0 00001913 ccid_usb.c:1307:InterruptRead() before (0) LIBUSB_FUNCTION: libusb_submit_transfer enter LIBUSB_FUNCTION: libusb_submit_transfer leave 0 LIBUSB_FUNCTION: libusb_handle_events_timeout_completed enter LIBUSB_FUNCTION: libusb10_handle_events_sub enter LIBUSB_FUNCTION: process_all *** HERE ^^ *** LIBUSB_FUNCTION: libusb10_handle_events_sub enter LIBUSB_FUNCTION: libusb_handle_events_timeout_completed exit 00026282 ccid_usb.c:1353:InterruptRead() after (0) (0) 00000006 NotifySlotChange: 50 02 00000006 -> 000000 65 00 00 00 00 00 00 00 00 00 LIBUSB_FUNCTION: libusb_submit_transfer enter LIBUSB_FUNCTION: libusb_submit_transfer leave 0 LIBUSB_FUNCTION: libusb_handle_events_timeout_completed enter LIBUSB_FUNCTION: libusb10_handle_events_sub enter LIBUSB_FUNCTION: libusb_handle_events_timeout_completed exit LIBUSB_FUNCTION: libusb_submit_transfer enter LIBUSB_FUNCTION: libusb_submit_transfer leave 0 LIBUSB_FUNCTION: libusb_handle_events_timeout_completed enter LIBUSB_FUNCTION: libusb10_handle_events_sub enter LIBUSB_FUNCTION: libusb_handle_events_timeout_completed exit 00002524 <- 000000 81 00 00 00 00 00 00 02 00 00 00000010 -> 000000 65 00 00 00 00 00 01 00 00 00 LIBUSB_FUNCTION: libusb_submit_transfer enter LIBUSB_FUNCTION: libusb_submit_transfer leave 0 LIBUSB_FUNCTION: libusb_handle_events_timeout_completed enter LIBUSB_FUNCTION: libusb10_handle_events_sub enter LIBUSB_FUNCTION: libusb_handle_events_timeout_completed exit LIBUSB_FUNCTION: libusb_submit_transfer enter LIBUSB_FUNCTION: libusb_submit_transfer leave 0 LIBUSB_FUNCTION: libusb_handle_events_timeout_completed enter LIBUSB_FUNCTION: libusb10_handle_events_sub enter LIBUSB_FUNCTION: libusb_handle_events_timeout_completed exit 00000496 <- 000000 81 00 00 00 00 00 01 02 00 00 00000010 ifdhandler.c:381:IFDHGetCapabilities() tag: 0xFB3, usb:2406/6407:libusb-1.0:0:2:0 (lun: 0) 00000006 readerfactory.c:396:RFAddReader() Using the reader polling thread 00000006 ifdhandler.c:1821:IFDHICCPresence() usb:2406/6407:libusb-1.0:0:2:0 (lun: 0) 00000009 -> 000000 65 00 00 00 00 00 02 00 00 00 LIBUSB_FUNCTION: libusb_submit_transfer enter LIBUSB_FUNCTION: libusb_submit_transfer leave 0 LIBUSB_FUNCTION: libusb_handle_events_timeout_completed enter LIBUSB_FUNCTION: libusb10_handle_events_sub enter LIBUSB_FUNCTION: libusb_handle_events_timeout_completed exit LIBUSB_FUNCTION: libusb_submit_transfer enter LIBUSB_FUNCTION: libusb_submit_transfer leave 0 LIBUSB_FUNCTION: libusb_handle_events_timeout_completed enter LIBUSB_FUNCTION: libusb10_handle_events_sub enter LIBUSB_FUNCTION: libusb_handle_events_timeout_completed exit 00000477 <- 000000 81 00 00 00 00 00 02 02 00 00 00000005 ifdhandler.c:1942:IFDHICCPresence() Card absent 00000046 ifdhandler.c:381:IFDHGetCapabilities() tag: 0xFAE, usb:2406/6407:libusb-1.0:0:2:0 (lun: 0) 00000008 ifdhandler.c:476:IFDHGetCapabilities() Reader supports 1 slot(s) 00000013 ifdhandler.c:1821:IFDHICCPresence() usb:2406/6407:libusb-1.0:0:2:0 (lun: 0) 00000013 -> 000000 65 00 00 00 00 00 03 00 00 00 LIBUSB_FUNCTION: libusb_submit_transfer enter LIBUSB_FUNCTION: libusb_submit_transfer leave 0 LIBUSB_FUNCTION: libusb_handle_events_timeout_completed enter LIBUSB_FUNCTION: libusb10_handle_events_sub enter LIBUSB_FUNCTION: libusb_handle_events_timeout_completed exit LIBUSB_FUNCTION: libusb_submit_transfer enter LIBUSB_FUNCTION: libusb_submit_transfer leave 0 LIBUSB_FUNCTION: libusb_handle_events_timeout_completed enter LIBUSB_FUNCTION: libusb10_handle_events_sub enter LIBUSB_FUNCTION: libusb_handle_events_timeout_completed exit 00000423 <- 000000 81 00 00 00 00 00 03 02 00 00 00000005 ifdhandler.c:1942:IFDHICCPresence() Card absent 00000005 ifdhandler.c:1821:IFDHICCPresence() usb:2406/6407:libusb-1.0:0:2:0 (lun: 0) 00000008 -> 000000 65 00 00 00 00 00 04 00 00 00 LIBUSB_FUNCTION: libusb_submit_transfer enter LIBUSB_FUNCTION: libusb_submit_transfer leave 0 LIBUSB_FUNCTION: libusb_handle_events_timeout_completed enter LIBUSB_FUNCTION: libusb10_handle_events_sub enter LIBUSB_FUNCTION: libusb_handle_events_timeout_completed exit LIBUSB_FUNCTION: libusb_submit_transfer enter LIBUSB_FUNCTION: libusb_submit_transfer leave 0 LIBUSB_FUNCTION: libusb_handle_events_timeout_completed enter LIBUSB_FUNCTION: libusb10_handle_events_sub enter LIBUSB_FUNCTION: libusb_handle_events_timeout_completed exit 00000489 <- 000000 81 00 00 00 00 00 04 02 00 00 00000005 ifdhandler.c:1942:IFDHICCPresence() Card absent 00000005 ifdhandler.c:310:IFDHPolling() usb:2406/6407:libusb-1.0:0:2:0 (lun: 0) 600000 ms 00000005 ccid_usb.c:1307:InterruptRead() before (0) LIBUSB_FUNCTION: libusb_submit_transfer enter LIBUSB_FUNCTION: libusb_submit_transfer leave 0 LIBUSB_FUNCTION: libusb_handle_events_timeout_completed enter LIBUSB_FUNCTION: libusb10_handle_events_sub enter LIBUSB_FUNCTION: libusb10_handle_events_sub enter 04249190 hotplug_libusb.c:626:HPRemoveHotPluggable() Removing USB device[0]: 0:2:0 00000009 readerfactory.c:610:RFRemoveReader() UnrefReader() count was: 1 00000004 eventhandler.c:175:EHDestroyEventHandler() Stomping thread. 00000004 ifdhandler.c:381:IFDHGetCapabilities() tag: 0xFB1, usb:2406/6407:libusb-1.0:0:2:0 (lun: 0) 00000004 ifdhandler.c:381:IFDHGetCapabilities() tag: 0xFB2, usb:2406/6407:libusb-1.0:0:2:0 (lun: 0) 00000004 eventhandler.c:200:EHDestroyEventHandler() Request stopping of polling thread 00000003 ifdhandler.c:346:IFDHStopPolling() usb:2406/6407:libusb-1.0:0:2:0 (lun: 0) LIBUSB_FUNCTION: libusb_cancel_transfer enter LIBUSB_FUNCTION: state: 1 LIBUSB_FUNCTION: entry.tqe_prev: 0x0 LIBUSB_FUNCTION: sxfer: 0x29007060 LIBUSB_FUNCTION: pxfer0: 0x28c2f348 LIBUSB_FUNCTION: pxfer1: 0x28c2f384 LIBUSB_FUNCTION: libusb20_tr_get_priv_sc1(pxfer0): 0x0 LIBUSB_FUNCTION: libusb20_tr_get_priv_sc1(pxfer1): 0x0 LIBUSB_FUNCTION: f LIBUSB_FUNCTION: libusb_cancel_transfer leave 00000023 ccid_usb.c:1401:InterruptStop() libusb_cancel_transfer failed: LIBUSB_ERROR_NOT_FOUND (In reply to Hans Petter Selasky from comment #8) Using libusb_set_debug(ctx, LIBUSB_DEBUG_TRANSFER); does not log anything. The only call site is in libusb10_do_transfer_cb() https://github.com/freebsd/freebsd/blob/master/lib/libusb/libusb10_io.c#L500 In libusb10_do_transfer_cb() the context is fetched using: ctx = GET_CONTEXT(NULL); Note the use of "NULL". so ctx->debug is always 0 and nothing is ever logged. The logging using LIBUSB_DEBUG_TRANSFER is bogus :-) I added a printf() in libusb10_do_transfer_cb() to get some log. This function is NOT called after I removed the USB device. (In reply to Hans Petter Selasky from comment #15) Where exactly should I add this code? In my code or in libusb? My code works fine using the "official" libusb on GNU/Linux and macOS. FreeBSD libusb should have the same behaviour if it claims to be compliant. No? > My code works fine using the "official" libusb on GNU/Linux and macOS.
FreeBSD libusb should have the same behaviour if it claims to be compliant. No?
I understand your frustration, but it is not always easy to be compliant. Some behaviours will be OS specific.
I'll try to come up with a second libusb patch to address this issue.
Can you try adding a call to libusb_check_connected(udevh) in your code to see what the value is?
--HPS
(In reply to Ludovic Rousseau from comment #17) I created a new bug about the non-working LIBUSB_DEBUG_TRANSFER level https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=231264 Created attachment 196991 [details]
LibUSB patch WIP
Second try.
I suspect libusb10_cancel_all_transfer() is called from the waiting loop and that will break the cancel logic because the priv_sc1 pointer is cleared.
I didn't have time yet to writeup a test program to verify the patch.
Your patch works for me. Now I have: LIBUSB_FUNCTION: libusb10_handle_events_sub enter 03008747 hotplug_libusb.c:626:HPRemoveHotPluggable() Removing USB device[0]: 0:2:0 00000009 readerfactory.c:610:RFRemoveReader() UnrefReader() count was: 1 00000003 eventhandler.c:175:EHDestroyEventHandler() Stomping thread. 00000005 ifdhandler.c:381:IFDHGetCapabilities() tag: 0xFB1, usb:2406/6407:libusb-1.0:0:2:0 (lun: 0) 00000003 ifdhandler.c:381:IFDHGetCapabilities() tag: 0xFB2, usb:2406/6407:libusb-1.0:0:2:0 (lun: 0) 00000003 eventhandler.c:200:EHDestroyEventHandler() Request stopping of polling thread 00000004 ifdhandler.c:346:IFDHStopPolling() usb:2406/6407:libusb-1.0:0:2:0 (lun: 0) LIBUSB_FUNCTION: libusb_cancel_transfer enter LIBUSB_FUNCTION: libusb_cancel_transfer leave LIBUSB_FUNCTION: libusb_handle_events_timeout_completed exit The libusb_cancel_transfer() function does return with no error. Great. libusb_handle_events_completed() now returns. Great. I now have another problem. I opened a new bug for that bug #231322. Thanks Created attachment 197050 [details]
LibUSB patch
Added code to handle cancel of pending transfers and block new ones after device detach is detected.
Can you please test?
This new patch works for me. It also fixes bug #231322. Good. I'll try to push this patch upstream then. Thank you for testing and being patient :-) --HPS *** Bug 231322 has been marked as a duplicate of this bug. *** A commit references this bug: Author: hselasky Date: Wed Sep 12 15:06:31 UTC 2018 New revision: 338616 URL: https://svnweb.freebsd.org/changeset/base/338616 Log: Fix issues about cancelling USB transfers in LibUSB when the USB device has been detached. When a USB device has been detached the kernel file handle stops responding to commands. USB applications which continue to run after the USB device has been detached, depend on LibUSB generated events to tear down its pending USB transfers. Add code to handle the needed cleanup when processing the USB transfer(s) fails and prevent new USB transfer(s) from being submitted. Found by: Ludovic Rousseau <ludovic.rousseau+freebsd@gmail.com> PR: 231076 MFC after: 1 week Approved by: re (gjb) Sponsored by: Mellanox Technologies Changes: head/lib/libusb/libusb10.c head/lib/libusb/libusb10.h head/lib/libusb/libusb10_io.c Will be MFC'ed to 10-stable in a week. A commit references this bug: Author: hselasky Date: Wed Sep 19 07:56:20 UTC 2018 New revision: 338788 URL: https://svnweb.freebsd.org/changeset/base/338788 Log: MFC r338616: Fix issues about cancelling USB transfers in LibUSB when the USB device has been detached. When a USB device has been detached the kernel file handle stops responding to commands. USB applications which continue to run after the USB device has been detached, depend on LibUSB generated events to tear down its pending USB transfers. Add code to handle the needed cleanup when processing the USB transfer(s) fails and prevent new USB transfer(s) from being submitted. Found by: Ludovic Rousseau <ludovic.rousseau+freebsd@gmail.com> PR: 231076 Sponsored by: Mellanox Technologies Changes: _U stable/11/ stable/11/lib/libusb/libusb10.c stable/11/lib/libusb/libusb10.h stable/11/lib/libusb/libusb10_io.c A commit references this bug: Author: hselasky Date: Wed Sep 19 07:57:31 UTC 2018 New revision: 338789 URL: https://svnweb.freebsd.org/changeset/base/338789 Log: MFC r338616: Fix issues about cancelling USB transfers in LibUSB when the USB device has been detached. When a USB device has been detached the kernel file handle stops responding to commands. USB applications which continue to run after the USB device has been detached, depend on LibUSB generated events to tear down its pending USB transfers. Add code to handle the needed cleanup when processing the USB transfer(s) fails and prevent new USB transfer(s) from being submitted. Found by: Ludovic Rousseau <ludovic.rousseau+freebsd@gmail.com> PR: 231076 Sponsored by: Mellanox Technologies Changes: _U stable/10/ stable/10/lib/libusb/libusb10.c stable/10/lib/libusb/libusb10.h stable/10/lib/libusb/libusb10_io.c A commit references this bug: Author: hselasky Date: Wed Sep 19 08:10:00 UTC 2018 New revision: 338790 URL: https://svnweb.freebsd.org/changeset/base/338790 Log: MFC r338616: Fix issues about cancelling USB transfers in LibUSB when the USB device has been detached. When a USB device has been detached the kernel file handle stops responding to commands. USB applications which continue to run after the USB device has been detached, depend on LibUSB generated events to tear down its pending USB transfers. Add code to handle the needed cleanup when processing the USB transfer(s) fails and prevent new USB transfer(s) from being submitted. Found by: Ludovic Rousseau <ludovic.rousseau+freebsd@gmail.com> PR: 231076 Sponsored by: Mellanox Technologies Changes: _U stable/9/lib/ _U stable/9/lib/libusb/ stable/9/lib/libusb/libusb10.c stable/9/lib/libusb/libusb10.h stable/9/lib/libusb/libusb10_io.c |