This problem may occur if the USB device driver has all of the following characteristics:
- The USB device driver is based on the Microsoft Windows Kernel Mode Driver Framework (KMDF) version 1.9 or earlier.
- The USB device driver implements a USB Continuous Reader to perform Read (IN) transfers from a Bulk IN or Interrupt IN pipe on the device.
- The USB device driver's D0Exit handler calls WdfIoTargetStop with a handle to the USB Device to stop all pending transfers for the device, without first calling WdfIoTargetStop with a handle to each USB Pipe belonging to the USB Device to stop all pending transfers for each of the device's USB pipes.
The problem may be more likely to occur, or occur more frequently, if the following condition is also true:
- The USB device driver does not implement an EvtReadersFailed callback routine for the USB Continuous Reader, or implements an EvtReadersFailed callback routine that returns TRUE for transfers that fail due to errors associated with the device being surprised removed such as STATUS_NO_SUCH_DEVICE or other unrecoverable errors.
Under this configuration, if the USB device is surprise-removed, USB transfers being performed by the USB Continuous Reader will complete with an error such as STATUS_NO_SUCH_DEVICE. If an
EvtReadersFailed callback routine is not registered for the USB Continuous Reader, the failed transfers are retried continuously.
Meanwhile, the USB device driver's
D0Exit handler may be called to handle the device surprise removal, and call
WdfIoTargetStop for the USB Device to stop all pending transfers. If the USB device driver's
D0Exit handler does not first call
WdfIoTargetStop with a handle to each USB Pipe belonging to the USB Device to stop all pending transfers for each of the device's USB pipes, a deadlock may occur which prevents Windows from completing removal of the device and unloading the device's driver.
In this scenario, there are two bugs in the Microsoft KMDF framework that can cause a
WdfIoTargetStop operation for a USB Device to hang while attempting to cancel pending transfers for a USB Continuous Reader:
- In preparation for cancelling pending USB transfers, the Microsoft KMDF framework issues a USB Get Port Status request to get the device's connection status, but does not set the WDF_REQUEST_SEND_OPTION_IGNORE_TARGET_STATE option. This may cause such requests to block indefinitely if the device is disconnected.
- The Microsoft KMDF framework's implementation of the WdfIoTargetStop method for a USB Device does not wait for pending transfers to complete for a Continuous Reader pipe. This may cause deadlocks between multiple threads performing actions for this device.