General question about allocating WDF objects or contexts in the I/O path

In one of my drivers I’m allocating an object context for each WDFREQUEST that comes into my I/O queue, and storing some stuff in it. It’s probably only about 20 bytes. There are never more than a few outstanding WDFREQUESTs sitting in a manual queue at any time – they are completed regularly.

In this same I/O path I might (depending on the circumstances) allocate a WDFTIMER and also store its handle in the above object context. This timer will be deleted either after it expires and the callback has run its course, or potentially before it has fired.

Is there any potential danger in doing things this way (for either approach – allocating contexts and attaching to WDFREQUESTs, or creating timers and putting them in the request context)?

I got a report that after about 1 hour of activity at roughly, say, 20 requests per second, the user’s machine reports (and I quote) “Windows reports that it can write to the Hard Drive and data will be lost,” followed by a total freeze of the machine (can’t move the mouse).

From a 100 foot view, this is fine. You might have a reference leak though and are slowing leaking memory to the point where you run out (although I would think you would get a low VM warning before you get disk write errors). Are you explicitly deleting the timer? Or assigning the request as the parent of the timer?

From a 1 foot perspective, if you are allocating context per request, have the framework do it for you up front by specifying the context type via WdfDeviceInitSetRequestAttributes.

If the mouse can’t move, that might be due to DPCs not being delivered or some other HW is stuck (which could also induce the disk write error if the disk cannot be reached).

d

Well, here’s the thing. I realized today that I can simplify my design to only have two, constant timers that I just enable and disable, so that problem drops out.

But to answer your question, I am/was explicitly deleting the timer with WdfObjectDelete() as the last line of my EvtTimerCallback() routine, in addition to its parent object being the WDFREQUEST which goes away.

I’ll also use WdfDeviceInitSetRequestAttributes() so that I am not calling WdfObjectAllocateContext() in the path, although I assume KMDF would just be doing the same behind the scenes.

I’m trying to reproduce the problem here so I can see what might happen. Would kernrate tell me about leaks of any kind? Or driver verifier?

What does your driver do? Do you sit in the storage path at all?

Has your customer looked at the amount of memory in use when the machine gets this error? It’s possible that you’re leaking something and running the machine out of pool - this can cause disk write failures if it becomes extreme.

-p

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Wednesday, January 24, 2007 2:20 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] General question about allocating WDF objects or contexts in the I/O path

In one of my drivers I’m allocating an object context for each WDFREQUEST that comes into my I/O queue, and storing some stuff in it. It’s probably only about 20 bytes. There are never more than a few outstanding WDFREQUESTs sitting in a manual queue at any time – they are completed regularly.

In this same I/O path I might (depending on the circumstances) allocate a WDFTIMER and also store its handle in the above object context. This timer will be deleted either after it expires and the callback has run its course, or potentially before it has fired.

Is there any potential danger in doing things this way (for either approach – allocating contexts and attaching to WDFREQUESTs, or creating timers and putting them in the request context)?

I got a report that after about 1 hour of activity at roughly, say, 20 requests per second, the user’s machine reports (and I quote) “Windows reports that it can write to the Hard Drive and data will be lost,” followed by a total freeze of the machine (can’t move the mouse).


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

Peter Wieland wrote:

What does your driver do? Do you sit in the storage path at all?

This is a USB driver – not in the storage path. I’m basically taking I/O from userspace and turning it into bulk reads and writes.

Has your customer looked at the amount of memory in use when
the machine gets this error? It’s possible that you’re leaking something
and running the machine out of pool - this can cause disk write failures
if it becomes extreme.

Well, trying to reproduce it here, I took a peek at task manager’s “Kernel Memory (K) Nonpaged Pool”. The value does go up steadily, albeit very slowly, when my driver is passing traffic. I assume that implicates me as leaking memory, somehow, right?

If I call WdfObjectAllocateContext(), I don’t have to manually delete that, right? It goes away when the request is completed?

I’m also pending some requests in a manual queue, and searching through them. If I eventually pull out the one in front, my call sequence looks like this:

WdfIoQueueFindRequest(…, &request1, …)
WdfIoQueueRetrieveFoundRequest(, …&request1, …, &request2…)
WdfObjectDereference(request1)

…which was the sequence recommended in the docs. Could I be leaking a reference here somehow? Would I leak the pool associated with request1 if I called WdfIoQueueFindRequest() and never WdfObjectDereference(request1)?

I don’t see any other places where I allocate pool, at least explicitly.

Yes, a context allocated by WdfObjectAllocateContext will be freed when the underlying object is freed. If you have a KMDF ref leak, !wdfdriverinfo should help with that as you would see a ton of objects in the hierarchy. I can’t remember if !wdfdriverinfo requires the KMDF verifier to be enabled, but my guess would be that it is not required.

d

I remember having difficulty creating timers with requests as their
parent objects. They never got deleted when the requests were deleted.
I had to explicitly declare a request cleanup callback and delete the
timer there. Is this known/expected behavior? I was using KMDF 1.1 at
the time. I no longer have access to the code so I can’t provide any
further info.

On 1/24/07, xxxxx@microsoft.com wrote:
> Yes, a context allocated by WdfObjectAllocateContext will be freed when the underlying object is freed. If you have a KMDF ref leak, !wdfdriverinfo should help with that as you would see a ton of objects in the hierarchy. I can’t remember if !wdfdriverinfo requires the KMDF verifier to be enabled, but my guess would be that it is not required.
>
> d
>
> —
> 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
>

The situation that Beverly is talking about can still happen in v1.5, although it can only occur if the request is completed at DISPATCH_LEVEL. Her solution is valid asl well

d

I’m assuming my request would be completed at DISPATCH_LEVEL because I’m using WdfSynchronizationScopeDevice, which means a lock is held when I get callbacks from KMDF, right?

For right now I’m going to take a shotgun approach to this:

  1. Move to two constant timers so that I don’t encounter Beverly’s problem

  2. WdfDeviceInitSetRequestAttributes() to simplify context allocation

  3. Double check all my WDFREQUEST references when I’m using the I/O queue find routines. Because of 1) I can simplify this a lot. I bet there is a leak in here somewhere.

I will post back with my findings.

After going through my code and cleaning it up per my previous description, I don’t seem to have any leaks now.

There were a few places where I may have been leaking a reference as a result of WdfIoQueueFindRequest, as well as timers not being deleted per Beverly’s description.