Cancel routine for current IRP

Devs,

I have a driver that can have an IRP in progress for up to an infinite
amount of time, if the external clock is lost. I have a customer who
terminates his application while one of the IRP buffers is still being
filled, which results in the driver corrupting the heap. I do have an I/O
timer going, and after some seconds the IRP will time out and complete.
Meanwhile the application is long gone.

One of our esteemed list members suggested adding a cancel routine to the
in-process IRP that turns off the flow of data and completes the IRP. I
plan to implement this, but…

There is quite a bit of superstition surrounding the use and misuse of
cancel routines. Under some conditions you want to grab the cancel
spinlock, unless you are managing your own queues (I am), yadda yadda yadda.

So the question: in the case of an in-process IRP, one that has already made
is past the StartIO routine, can I assume that I will not have anything
pathological happen if I simply set a cancel routine before I start copying
data, Queue my DPC if the in-process cancel fires, and either way set the
cancel routine to NULL in my DPC after a successful or unsuccessful
transfer?

Thanks,

Evan

Evan Hillman
General Standards
435-755-0309


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

I would recommend the latest article from Peter V. in NTInsider on
cancellation of Irps. And to answer your question, it depends …

Pete

Peter Scott
xxxxx@KernelDrivers.com
http://www.KernelDrivers.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of Evan Hillman
Sent: Friday, November 09, 2001 1:20 PM
To: NT Developers Interest List
Subject: [ntdev] Cancel routine for current IRP

Devs,

I have a driver that can have an IRP in progress for up to an infinite
amount of time, if the external clock is lost. I have a customer who
terminates his application while one of the IRP buffers is still being
filled, which results in the driver corrupting the heap. I do have an I/O
timer going, and after some seconds the IRP will time out and complete.
Meanwhile the application is long gone.

One of our esteemed list members suggested adding a cancel routine to the
in-process IRP that turns off the flow of data and completes the IRP. I
plan to implement this, but…

There is quite a bit of superstition surrounding the use and misuse of
cancel routines. Under some conditions you want to grab the cancel
spinlock, unless you are managing your own queues (I am), yadda yadda yadda.

So the question: in the case of an in-process IRP, one that has already made
is past the StartIO routine, can I assume that I will not have anything
pathological happen if I simply set a cancel routine before I start copying
data, Queue my DPC if the in-process cancel fires, and either way set the
cancel routine to NULL in my DPC after a successful or unsuccessful
transfer?

Thanks,

Evan

Evan Hillman
General Standards
435-755-0309


You are currently subscribed to ntdev as: xxxxx@home.com
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

“Evan Hillman” wrote in message news:xxxxx@ntdev…
>
> So the question: in the case of an in-process IRP, one that has already
made
> is past the StartIO routine, can I assume that I will not have anything
> pathological happen if I simply set a cancel routine before I start
copying
> data, Queue my DPC if the in-process cancel fires, and either way set the
> cancel routine to NULL in my DPC after a successful or unsuccessful
> transfer?
>

In general, yeah… I think that’ll work. Of course, as Pete said, “it
depends”…

Consider the case where your Cancel function fires, you queue the DPC, it
starts to run, and just then (on another processor) an interrupt occurs to
signal that your IRP is complete (I’m presuming your device functions this
way, of course) and the ISR queues the DPC and IT starts to run.

Hmmmm… Obviously, you need to resolve potential race conditions like this.
And hence the pain of cancel.

HTH,

Peter
OSR


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

I’m confused as to how the “application is long gone”. The IRP_MJ_CLOSE will not occur until the
IRPS are returned (or you get the timeout IRP pop-up after a long time). I would have expected the
application to be "dead-but-not-burried’ if you weren’t giving back the IRP.

I’ve always believed that the lowest risk way to write a cancel routine is to have it release the
cancel spin lock, and search (with your locks held) for any IRP that has IRP::Cancel set, dequeue it, and
return it with STATUS_CANCELLED. This way, you need not worry about the cancelled IRP
completing before you get to it.

If your enqueue code looks like:

Get Lock
if (irp->Cancel) { // handles case where the IRP was cancelled before your driver got it).
Release lock

}
set cancel routine
enqueue
release

its pretty safe from races.

The DDK descriptions of cancel starting with Win2K are also viable (NT 4 DDK did not present a coorect cancel example).

-DH

PS. If you work through the DDK, you’ll find that NT must set Irp::Cancel before calling the cancel routine.
PPS. If you enqueue the IRP using the Interlocked… List functions, its unlikely that you’ll ever correctly implement cancel.

----- Original Message -----
From: “Evan Hillman”
To: “NT Developers Interest List”
Sent: Friday, November 09, 2001 3:19 PM
Subject: [ntdev] Cancel routine for current IRP

> Devs,
>
> I have a driver that can have an IRP in progress for up to an infinite
> amount of time, if the external clock is lost. I have a customer who
> terminates his application while one of the IRP buffers is still being
> filled, which results in the driver corrupting the heap. I do have an I/O
> timer going, and after some seconds the IRP will time out and complete.
> Meanwhile the application is long gone.
>
> One of our esteemed list members suggested adding a cancel routine to the
> in-process IRP that turns off the flow of data and completes the IRP. I
> plan to implement this, but…
>
> There is quite a bit of superstition surrounding the use and misuse of
> cancel routines. Under some conditions you want to grab the cancel
> spinlock, unless you are managing your own queues (I am), yadda yadda yadda.
>
> So the question: in the case of an in-process IRP, one that has already made
> is past the StartIO routine, can I assume that I will not have anything
> pathological happen if I simply set a cancel routine before I start copying
> data, Queue my DPC if the in-process cancel fires, and either way set the
> cancel routine to NULL in my DPC after a successful or unsuccessful
> transfer?
>
> Thanks,
>
> Evan
>
> Evan Hillman
> General Standards
> 435-755-0309
>
>
> —
> You are currently subscribed to ntdev as: xxxxx@syssoftsol.com
> To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com