Profiling UMDF Drivers

Hi,

Any recommended tools for profiling and detecting memory leaks in user mode drivers?
(I’ve searched previous posts and they deal with kernel mode drivers).

Thanks,
Gadi

You may be able to use Visual Studio for profiling. I haven’t used it
directly. I’ve used an internal version of the profiler, which is what I
suspect is integrated with VS.

The following link seems to have info on it:

http://www.learnvisualstudio.net/content/videos/vsts_005_profiling_windo
ws_applications.aspx

For detecting leaks you can use UMDF and OH for heap and handle leaks
respectively. These are resource kit tools. I found the following links
for them (although they refer to really old resource kit):

UMDH

http://support.microsoft.com/kb/268343

OH

http://support.microsoft.com/kb/172710

For both of these you can take snapshots at IDriverEntry::OnInitialize
and OnDeinitialize and compare them.

As such UMDF host process is just another user mode process so you can
use any other tools available for user mode apps.

HTH,

Praveen

Writing a user mode leak-detecting allocator is trivial (1 C++ class and 1
global object of this clas).


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntdev…
> Hi,
>
> Any recommended tools for profiling and detecting memory leaks in user mode
drivers?
> (I’ve searched previous posts and they deal with kernel mode drivers).
>
> Thanks,
> Gadi
>

Hi,
I’ve run umdh on my driver (on the WUDFHost.exe process), and it found memory leaks in CMyDevice::SendControlTransferSynchonously (in CreateRequest and CreatePreAllocatedWdfMemory).
There are (minor) changes from the FX2 code.
I have a few questions which will help me resolve the leaks:

  1. Who is responsible to de-allocate the request and memory objects? Whereas in the ReadWriteQueue they are created in the CMyDevice::InitiatePendingRead and released in CMyReadWriteQueue::OnCompletion, I see that in SendControlTransferSynchonously the request object is deleted in the same method itself, and the memory is only released.
    How can it be that that request remains and causes a leak? And where is this memory actually deleted?
  2. I’ve tried adding a completion callback to that request, and delete the objects there, but I must be doing something wrong because this callback is not invoked.
    This is what I’ve done:
    I’m haven’t been using the original CMyDevice::OnCompletion, so I added it as callback to that request, in two ways, both failed:
    a. Before pWdfRequest->Send I added

IRequestCallbackRequestCompletion * pCompletionCallback = NULL;
HRESULT hrQI = this->QueryInterface(IID_PPV_ARGS(&pCompletionCallback));
WUDF_TEST_DRIVER_ASSERT(SUCCEEDED(hrQI) && (NULL != pCompletionCallback));

pWdfRequest->SetCompletionCallback(
pCompletionCallback,
NULL
);

pCompletionCallback->Release();
pCompletionCallback = NULL;

The driver could not start (Code 10)

b. Second attempt – while creating the request:
hr = m_FxDevice->CreateRequest( static_cast(this), //pCallbackInterface
NULL, //pParentObject
&pWdfRequest);
This time the driver did function properly, but the OnCompletion callback was not invoked, and the memory leaks continued.
Any thoughts?
Thanks,
Gadi

Hi Gadi,

Sorry for the delayed reply.

#1 With UMDF you have two lifetime models with somewhat overlapping
functionality - COM lifetime management and WDF lifetime management. You
need to take care of both. To take care of COM lifetime management:

* You need to make sure that you release references correctly
(this is same as general COM usage).

* If reference is released early, it doesn’t meant that object
actually gets destroyed right away, because WDF object tree keeps a
reference on the object. For example, UMDF samples release the device
object right away after calling IWDFDriver::CreateDevice. But device
object would hang around until device removal because WDF object tree
keeps a reference on it. If you do keep an outstanding reference (as
customary with COM) it doesn’t hurt as long as you don’t get into
circular reference (which you can unfortunately easily run into since
UMDF object keeps a reference on the callback object such as CMyDevice
and if callback object held a strong reference to framework device
object you will have circular reference).

For WDF lifetime model you need to:

* Either use the appropriate parenting which will take care of
WdfDelete’ing the object (which gives up the object tree reference)

* Or call IWDFObject::DeleteWdfObject

Appropriate parenting is the preferred way so that driver doesn’t have
to explicitly DeleteWdfObject. But there are cases when there is no
parent whose lifetime closely matches object’s lifetime. In that case
you need to use explicit DeleteWdfObject. In the example you mentioned,
memory is parented to request hence doesn’t need to be deleted
explicitly. But the newly created request can’t really be parented to
anything which has a closely matching lifetime. If you parent it to
device, these requests would hang around until device removal
unnecessarily. Hence sample calls DeleteWdfObject on request explicitly.

But COM references are given up for both memory and request as usual.

#2 Completion callback is not useful in this case because request is
sent in synchronous manner.

Now to the problem you are running into:

We are not aware of any leaks in the unmodified fx2 samples. Do you see
this behavior even with unmodified sample?

When do you take the snapshots - at driver init and deinit? If there are
objects parented to the driver they would not be freed up by deinit time
and hence would show up as false positive leaks. Although in unmodified
fx2 sample preallocated memory is parented to request so I am not sure
why it would not be freed up by deinit time. We will try on our end.

Alternatively you can use the in-built object tracking of UMDF. To do
that, set

  1. HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows
    NT\CurrentVersion\WUDF\Services{193a1820-d9ac-4997-8c55-be817523f6aa}\T
    rackObjects to 1.

  2. Disable the device, run your scenario(s) and disable the device.

  3. If there are any leaks UMDF will generate a DriverStop and prompt
    you to use !wudfext.dumpobjects

    4) Load UMDF debugger extension (wudfext.dll from WDK) and run the
    prompted command

    5) It will list the leaked WDF objects for you.

    Please note that this tracking only catches leaked WDF objects and not
    raw memory allocations. If you don’t do the latter then you’d be fine
    just with this tracking.

    HTH,

    Praveen