KMDF filter driver crash after surprise removal and DeviceIOControl

I have a KMDF USB lower filter driver with a sideband control device. Currently, I am creating the control device from my EvtDeviceAdd callback (if my physical device collection count is 1) and deleting it from my EvtCleanupCallback callback (if my physical device collection count is 0). I am using a global collection to keep track of these physical device instances. I believe this was may have been from the toaster example. I am trying to make sure I got rid of all freezes and crashes involving removing and upgrading the driver.

I have at least one remaining crash problem. If the cable is pulled (surprise removal) while a user application still has the control device open, calling DeviceIOControl seems to instantly crash my machine without a bluescreen. I am guessing this is because the control device has already been closed. My D0Exit etc. routines get called, but not DriverUnload itself because the handle is still open.

  1. Does anyone have general suggestions about problems that crash the machine without generating a bluescreen? Is this unavoidable behavior if something happens like a NULL-pointer dereference in the driver, and there is no way to get a memory dump from it?

  2. Is there any proper way to fix this by synchronizing control device open and close calls? An OSR example I followed originally has an option to do something like that, but it says the following:

//
// *** This check is entirely NOT thread safe, we could be
// in the middle of processing an open as we speak.
// However, protecting this code against the EvtCreate
// callback only makes the BSOD window smaller and doesn’t
// really close it, so we don’t bother serializing and
// only do this in the checked build (where an
// occasional crash is OK)
//
if (WdfFltrControlDeviceOpen) {
WdfFltrTrace(("Not allowing remove of device 0x%p, control "\
“device is open…\n”, Device));
//
// The device didn’t really go away…
//
InterlockedIncrement(&WdfFltrDeviceCount);
return STATUS_DEVICE_BUSY;
}

So, is there any way to safely delete a control device? My intention is to synchronize on the same WDFWAITLOCK that protects my physical device collection and my control device deletion call. This should make the control device permanently available until it is reloaded and shutdown again, but I want to make sure that the comment from the example code above is no longer valid regarding the risk of a BSOD.

As a footnote, I have seen the thread here:
http://www.eggheadcafe.com/software/aspnet/33061164/kmdf-filter-driver.aspx
It is in regards to closing a control device and unloading a driver. The suggested approach #3 sounds nice though I am unsure how to completely develop it.

Could I simply delete the control device in the EvtFileClose handler, if there are no more references to my device? My driver is supposedly exclusive to a single application, which might make things even easier.

Thanks for reading!

xxxxx@gmail.com skrev 2010-11-25 22:07:

I have a KMDF USB lower filter driver with a sideband control device. Currently, I am creating the control device from my EvtDeviceAdd callback (if my physical device collection count is 1) and deleting it from my EvtCleanupCallback callback (if my physical device collection count is 0). I am using a global collection to keep track of these physical device instances. I believe this was may have been from the toaster example. I am trying to make sure I got rid of all freezes and crashes involving removing and upgrading the driver.

I have at least one remaining crash problem. If the cable is pulled (surprise removal) while a user application still has the control device open, calling DeviceIOControl seems to instantly crash my machine without a bluescreen. I am guessing this is because the control device has already been closed. My D0Exit etc. routines get called, but not DriverUnload itself because the handle is still open.

Can’t you just check your global collection count, and if zero, just return failure on your IOCTLs ?

/Rob

> Can’t you just check your global collection count, and if zero, just return failure on your IOCTLs ?

Thanks for the response. Maybe I was missing something, but it seemed like I would not even get the handler to run properly because the control device had been closed. However, I may have it working now. My current code is something like this:

  1. Track an open handle count by using file create and file close handlers on the control device. This count is protected by the same wait lock that protects a global handle to my control device, a global physical device collection, and a global boolean indicating whether the device is “available”.

  2. As part of cleanup for the device being removed, check if there are still open handles. If not, delete the device. In either case, mark the device as “unavailable” via the global boolean.

  3. If the device was removed by surprise, but there was still an open handle, then the device will stay in existence until it is plugged back in and then removed in a state where there are no open handles. If any user IOCTLs come in to the control device during that time period, however, I immediately return failure.

  4. When the device starts back up, I create it if necessary (if my global handle is NULL) from the EvtDeviceAdd handler. The device may be created, or it may already exist, but in either case I then mark it as “available” in the D0Entry handler, and IOCTLs can once again used successfully.

This seems to work well with no freezes or crashes. I just wanted to make sure that the logic made sense due to the warning in that example code that there could be synchronization issues. I seem to remember Doron mentioning at least one problem back in WDF 1.0 that had been fixed, possibly involving control device deletion and creation synchronization.