KMDF Question

I am looking at a full dump delivered to me by a client, for a KMDF
driver I wrote. My ISR has been called. The first couple of lines of
my ISR look basically like this:

BOOLEAN
XxxEvtInterruptIsr(
IN WDFINTERRUPT Interrupt,
IN ULONG MessageID
)
{
PDEVICE_EXTENSION devExt;
BOOLEAN isRecognized = FALSE;
UNREFERENCED_PARAMETER(MessageID);
devExt = XxxGetDeviceContext(WdfInterruptGetDevice(Interrupt));

// Read the interrupt status register.

ULONG intstat = READ_REGISTER_ULONG( &devExt->StatusRegs->IntStatus );

In the dump, WdfInterruptGetDevice has returned NULL. I then got a
FxVerifierNullBugCheck from WdfObjectGetTypedContextWorker.

I’m confused by this. It’s easy enough for me to add a check for NULL,
but none of the samples do that. Even if I get an interrupt on the same
ISR from a different client, the WDFINTERRUPT object that I get should
be my driver, right?

How could this happen?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

From time to time I would get crash dumps where WdfWhateverGetDevice(WhateverObj) was returning NULL. I basically went through all my code and checked for NULLs on all of these calls, and have been happier for it.

No idea why it happens (“Get” calls should be atomic/always-succeed’s, right? … as opposed to “retrieve” or “query”?) but just echoing your experience.

are you using KMDF to manage the enabled state of the interrupt? What
is the pnp and power state of your device in the dump ? since it’s a
full dump, !wdfkd.wdfdevice should work so please send the output of
that command along with the output of !wdfkd.wdfhandle

WdfInterruptGetDevice can return NULL after the WDFINTERRUPT has been
cleaned up, but you should not have your ISR hooked up to the
WDFINTERRUPT by the time the interrupt object has started the rundown
process

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Wednesday, December 13, 2006 11:52 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] KMDF Question

I am looking at a full dump delivered to me by a client, for a KMDF
driver I wrote. My ISR has been called. The first couple of lines of
my ISR look basically like this:

BOOLEAN
XxxEvtInterruptIsr(
IN WDFINTERRUPT Interrupt,
IN ULONG MessageID
)
{
PDEVICE_EXTENSION devExt;
BOOLEAN isRecognized = FALSE;
UNREFERENCED_PARAMETER(MessageID);
devExt = XxxGetDeviceContext(WdfInterruptGetDevice(Interrupt));

// Read the interrupt status register.

ULONG intstat = READ_REGISTER_ULONG( &devExt->StatusRegs->IntStatus
);

In the dump, WdfInterruptGetDevice has returned NULL. I then got a
FxVerifierNullBugCheck from WdfObjectGetTypedContextWorker.

I’m confused by this. It’s easy enough for me to add a check for NULL,
but none of the samples do that. Even if I get an interrupt on the same
ISR from a different client, the WDFINTERRUPT object that I get should
be my driver, right?

How could this happen?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Chris, if any of the Get calls are returning NULL then you are using the object after it has been cleaned up (and maybe not yet destroyed). The whole point of the EvtObjectCleanup() routine is to stop all other threads/actors from touching the object anymore so that it can safely go away. I would like to know how you set up your object hierarchy and where you were getting NULL.

d

Well, here’s an example that sticks out in my mind.

In my USB modem driver I have a default/sequential queue that gets reads from user space, and a manual queue where I pend the reads until they can be satisfied from the continuous reader.

Depending on the user’s COMMTIMEOUTS settings I sometimes have to queue a WDF timer, and then potentially complete a pended request inside the timer timeout callback, for example if some data came in during the timer period.

So, inside EvtTimerTimeout I call:

  1. WDFREQUEST Request = WdfTimerGetParentObject(Timer), followed by
  2. WDFIOQUEUE ioQueue = WdfRequestGetIoQueue(Request).

The latter call was returning NULL from time to time.

Most likely b/c the request was already completed. Just b/c you have a reference to the object does not mean its state is intact, you need to track state yourself in this case.

d

The KMDF documentation says: “The WdfRequestGetIoQueue method returns a handle to the framework queue object from which a specified I/O request was delivered.”

It merely says you get a handle to the queue from which the request came. It doesn’t say anything about tracking the state of the WDFREQUEST. What difference does it make if the request is complete or not? It still had to come from somewhere.

In fact, they specifically give you this example in the help file:

device = WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request));

That will give you a nice bugcheck in this scenario.

If you complete the request it is no longer in a queue (otherwise the queue wold still be tracking it). I will have the docs updated to reflect this

d