CloseHandle while DMA in progress

Hi all,

I’m interested in understanding how to deal with this kind of problem.
Imagine that a thread of an application performs the following actions :

  1. CreateFile()
  2. Allocate memory
  3. Several overlapped ReadFile() from device to allocated memory
  4. ExitProcess() because of a huge bug inside another thread

What happens?
I guess that :

  1. Windows releases the memory
  2. Windows calls CloseHandle()

As the memory is still locked by the driver, it is not made available to other threads; right?
But what happens from driver point of view?
What does CloseHandle() perform on driver side?
How do I wait for all ReadFile() to be terminated?

I have a KMDF driver:

  • What happens for ReadFile() requests that are inside the IoQueue waiting for EvtIoRead callback to be called?
  • What happens to the request owned by the driver, i.e. the one currently under DMA?

I have to admit I’m a little bit lost/confused, and the documentation I read doesn’t help me a lot :frowning:

Thank you.
Vincent

You will get IRP_MJ_CANCEL’s for the I/O but not a close until the I/O
is completed. So you don’t have to wait for the ReadFile’s to be
completed, the system does it for you.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

xxxxx@cea.fr” wrote in
message news:xxxxx@ntdev:

> Hi all,
>
> I’m interested in understanding how to deal with this kind of problem.
> Imagine that a thread of an application performs the following actions :
> 1. CreateFile()
> 2. Allocate memory
> 3. Several overlapped ReadFile() from device to allocated memory
> 4. ExitProcess() because of a huge bug inside another thread
>
> What happens?
> I guess that :
> 1. Windows releases the memory
> 2. Windows calls CloseHandle()
>
> As the memory is still locked by the driver, it is not made available to other threads; right?
> But what happens from driver point of view?
> What does CloseHandle() perform on driver side?
> How do I wait for all ReadFile() to be terminated?
>
> I have a KMDF driver:
> - What happens for ReadFile() requests that are inside the IoQueue waiting for EvtIoRead callback to be called?
> - What happens to the request owned by the driver, i.e. the one currently under DMA?
>
> I have to admit I’m a little bit lost/confused, and the documentation I read doesn’t help me a lot :frowning:
>
> Thank you.
> Vincent

Thank you Don.

You mean IRP_MJ_CLEANUP for the file object?
I didn’t find any reference to IRP_MJ_CANCEL.

So, the system:

  • Sends IRP_MJ_CLEANUP
  • Waits for all ReadFile() to complete
  • Sends IRP_MJ_CLOSE
    That’s it?

And for ReadFile() operations that cannot complete until an interrupt from the device occurs for example?
They will wait forever or is there a way to cancel specific ReadFile() requests?

Vincent

Sorry I meant CANCEL of the request, not IRP_MJ_CANCEL (fighting a cold
this morning). You can register for CANCEL notification with KMDF, or
let the system wait.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

xxxxx@cea.fr” wrote in
message news:xxxxx@ntdev:

> Thank you Don.
>
> You mean IRP_MJ_CLEANUP for the file object?
> I didn’t find any reference to IRP_MJ_CANCEL.
>
> So, the system:
> - Sends IRP_MJ_CLEANUP
> - Waits for all ReadFile() to complete
> - Sends IRP_MJ_CLOSE
> That’s it?
>
> And for ReadFile() operations that cannot complete until an interrupt from the device occurs for example?
> They will wait forever or is there a way to cancel specific ReadFile() requests?
>
> Vincent

OK, I can register to cancel notifications using WdfRequestMarkCancelable().
If this function is called, then the request will be cancelled upon CloseHandle() and IoCancel(), right?

So, what I can do is:

  • When the request is just owned by the driver inside the EvtIoRead callback, call WdfRequestMarkCancelable().
  • As soon as the device is ready to process the request and before triggering the DMA, call WdfRequestUnmarkCancelable().
    Is that the usual way of using those functions?

Thank you.

Vincent

> What happens?

I guess that :

  1. Windows releases the memory
  2. Windows calls CloseHandle()

This will be delayed till the overlapped IO will complete.

Yes, the attempt to cancel this IO will be done first.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

> OK, I can register to cancel notifications using WdfRequestMarkCancelable().

When the request is in the queue, it is cancellable even without this, provided the queue has correct creation flags.

This call is only to make the request cancellable after it was consumed from the queue.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Max’s answer is correct, but confusing. If the request is in the queue, but not yet presented to the driver, the queue will handle the cancelation and complete the request before the driver ever sees it. Once the request has been presented to your driver via EvtIoRead (or any other EvtIoXxx routine you register with a queue), cancelation is up to the driver while the request is active. WdfRequestMarkCancelable (and its opposite) are how you do that once you have the request in your hands (or you fwd it to a manual queue). If you fwd the request to another queue and it is canceled before it is presented on that 2ndary queue, you can register an EvtIoCanceledOnQueue callback to handle that situation.

d
-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Maxim S. Shatskih
Sent: Monday, March 21, 2011 9:38 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] CloseHandle while DMA in progress

OK, I can register to cancel notifications using WdfRequestMarkCancelable().

When the request is in the queue, it is cancellable even without this, provided the queue has correct creation flags.

This call is only to make the request cancellable after it was consumed from the queue.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

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

OK, thank you for the explanations.
The doc was fairly clear about that, but I think I read it too fast :frowning:

Vincent

All of which is fine. The difficult part is doing something with your
hardware for cancelled requests that are on the hardware. The easy way
out is ‘do nothing’, but this may result in user frustration if the
lag between do nothing after cancel and the hardware processing of the
request or requests being cancelled is ‘long enough’.

Mark Roddy

On Mon, Mar 21, 2011 at 12:43 PM, Doron Holan wrote:
> Max’s answer is correct, but confusing. ?If the request is in the queue, but not yet presented to the driver, the queue will handle the cancelation and complete the request before the driver ever sees it. ?Once the request has been presented to your driver via EvtIoRead (or any other EvtIoXxx routine you register with a queue), cancelation is up to the driver while the request is active. ?WdfRequestMarkCancelable (and its opposite) are how you do that once you have the request in your hands (or you fwd it to a manual queue). ?If you fwd the request to another queue and it is canceled before it is presented on that 2ndary queue, you can register an EvtIoCanceledOnQueue callback to handle that situation.
>
> d
> -----Original Message-----
> From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Maxim S. Shatskih
> Sent: Monday, March 21, 2011 9:38 AM
> To: Windows System Software Devs Interest List
> Subject: Re:[ntdev] CloseHandle while DMA in progress
>
>> OK, I can register to cancel notifications using WdfRequestMarkCancelable().
>
> When the request is in the queue, it is cancellable even without this, provided the queue has correct creation flags.
>
> This call is only to make the request cancellable after it was consumed from the queue.
>
> –
> Maxim S. Shatskih
> Windows DDK MVP
> xxxxx@storagecraft.com
> http://www.storagecraft.com
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
>

When a thread exits, or get terminated (possibly as a part of process exit or termination) all incomplete I/O requests issued from that thread will receive a cancel callback (as if IoCancelIrp was called for them). A thread or process termination will only proceed after all those requests are completed (aborted or allowed to complete naturally, as the driver decides).

Next, all handles belonging to the process will be closed. If a handle is not duplicated to another process, IRP_MJ_CLEANUP will be issued to the FILE_OBJECT stack.

When all I/O requests are completed on that FILE_OBJECT, it will get IRP_MJ_CLOSE. That’s the end of it.

Thank you all for your answers.

If I summarize (tell me if I’m wrong):

  • All requests that are inside an IoQueue (either on behalf of the framework or on behalf of the driver through a call to WdfRequestForwardToIoQueue) will be cancelled without the driver knowing what happens; if the driver wants to know, it can register an EvtIoCanceledOnQueue callback
  • All requests that are owned by the driver will wait for termination; if the driver wants to cancel them, it has to register an EvtRequestCancel callback using WdfRequestMarkCancelable or WdfRequestMarkCancelableEx

So, the default behaviour is:

  • Cancel all requests owned by the framework
  • Wait for all requests owned by the driver to terminate

This default behaviour fits my needs perfectly :slight_smile:
It allows me to avoid trying to abort pending DMA transfers as long as the latency is not too high for my needs.

Vincent