Mombu the Microsoft Forum sponsored links

Go Back   Mombu the Microsoft Forum > Microsoft > WINDOWS PROGRAMMING (NNTP) > remove cancel routine of IRP
User Name
Password
REGISTER NOW! Mark Forums Read

sponsored links


Reply
 
1 11th July 14:30
frank van eijkelenburg
External User
 
Posts: 1
Default remove cancel routine of IRP



I was running a test for my own driver and it took 5 days before the system crashed. The ****yzed minidump show the following:

************************************************** *****************************
* *
* Bugcheck ****ysis *
* *
************************************************** *****************************

Use !****yze -v to get detailed debugging information.

BugCheck A, {38, 2, 1, 805369d8}

Probably caused by : Pecx.sys ( Pecx!PecxCommandCallBack+497 )

Followup: MachineOwner
---------

0: kd> !****yze -v
************************************************** *****************************
* *
* Bugcheck ****ysis *
* *
************************************************** *****************************

IRQL_NOT_LESS_OR_EQUAL (a)
An attempt was made to access a pageable (or completely invalid) address at an
interrupt request level (IRQL) that is too high. This is usually
caused by drivers using improper addresses.
If a kernel debugger is available get the stack backtrace.
Arguments:
Arg1: 00000038, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000001, value 0 = read operation, 1 = write operation
Arg4: 805369d8, address which referenced memory

Debugging Details:
------------------


WRITE_ADDRESS: 00000038

CURRENT_IRQL: 2

FAULTING_IP:
nt!Exfi386InterlockedExchangeUlong+0
805369d8 8711 xchg [ecx],edx

CUSTOMER_CRASH_COUNT: 1

DEFAULT_BUCKET_ID: DRIVER_FAULT

BUGCHECK_STR: 0xA

LAST_CONTROL_TRANSFER: from bac704f7 to 805369d8

TRAP_FRAME: f78a6ef4 -- (.trap fffffffff78a6ef4)
ErrCode = 00000002
eax=00000000 ebx=ffdff000 ecx=00000038 edx=00000000 esi=ffdff9c0 edi=894723b8
eip=805369d8 esp=f78a6f68 ebp=f78a6fbc iopl=0 nv up ei pl zr na po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246
nt!Exfi386InterlockedExchangeUlong:
805369d8 8711 xchg [ecx],edx ds:0023:00000038=????????
Resetting default scope

STACK_TEXT:
f78a6f64 bac704f7 ffdff9c0 0000000c 896fd8b2 nt!Exfi386InterlockedExchangeUlong
f78a6fbc bac70e13 896f70e0 896f70e0 ffdff980 Pecx!PecxCommandCallBack+0x497 [c:\proj\atm03001\hdl\pci_driver\wxp\pecx.c @ 333]
f78a6fcc 80535dcf 896f7770 896f70e0 896f70e0 Pecx!PecxDpc+0x13 [c:\proj\atm03001\hdl\pci_driver\wxp\pecx.c @ 778]
f78a6ff4 8053593b a3f9094c 00000000 00000000 nt!KiRetireDpcList+0x61


FOLLOWUP_IP:
Pecx!PecxCommandCallBack+497 [c:\proj\atm03001\hdl\pci_driver\wxp\pecx.c @ 333]
bac704f7 85c0 test eax,eax

SYMBOL_STACK_INDEX: 1

FOLLOWUP_NAME: MachineOwner

SYMBOL_NAME: Pecx!PecxCommandCallBack+497

MODULE_NAME: Pecx

IMAGE_NAME: Pecx.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 43ec76d7

STACK_COMMAND: .trap fffffffff78a6ef4 ; kb

FAILURE_BUCKET_ID: 0xA_W_Pecx!PecxCommandCallBack+497

BUCKET_ID: 0xA_W_Pecx!PecxCommandCallBack+497

Followup: MachineOwner
---------

_____________________________________

The last line of code executed in my driver is line 333 (see above):

323 /*
324 * Check for a pending IRP. If a pending IRP exists, we have to make sure
325 * that the cancel routine is not called before handling the IRP otherwise
326 * we must allow the cancel routine to complete the IRP.
327 */
328 Irp = NULL;
329 if (pDE->PecIrp[Channel] == NULL) {
330 IrpExists = FALSE;
331 } else {
332 IoAcquireCancelSpinLock(&CancelIrql);
333 if (IoSetCancelRoutine(pDE->PecIrp[Channel], NULL) == NULL) {
334 /*
335 * The cancel routine was called. So allow the cancel routine to complete
336 * the IRP.
337 */
338 IrpExists = FALSE;
339 } else {
340 Irp = InterlockedExchangePointer(&pDE->PecIrp[Channel], NULL);
341 IrpExists = TRUE;
342 }
343
344 IoReleaseCancelSpinLock(CancelIrql);
345 }
346

It crashed at the call IoSetCancelRoutine. The only thing I can think about is that "pDE->PecIrp[Channel]" is an invalid address.

Are there any other reasons to let it crash at this routine? Or do I interpret the minidump wrong?

TIA,
Frank
  Reply With Quote


  sponsored links


2 11th July 14:30
don burn
External User
 
Posts: 1
Default remove cancel routine of IRP



Consider that IoSetCancelRoutine is:

#define IoSetCancelRoutine( Irp, NewCancelRoutine ) ( \
(PDRIVER_CANCEL) InterlockedExchangePointer( (PVOID *)
&(Irp)->CancelRoutine, (PVOID) (NewCancelRoutine) ) )

I think you can safely say it is your iRP pointer.

--
Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Remove StopSpam from the email to reply
  Reply With Quote
3 11th July 14:30
alexander grigoriev
External User
 
Posts: 1
Default remove cancel routine of IRP


You have a race condition window between a point you check if
(pDE->PecIrp[Channel] == NULL) and IoAcquireCancelSpinLock. Another thread
invalidated (zeroed) the pointer in between. Remember then, since you don't
have any other spinlock, ALL accesses to that MUST be protected by the
cancel spinlock.
  Reply With Quote
4 11th July 14:30
frank van eijkelenburg
External User
 
Posts: 1
Default remove cancel routine of IRP


So next change should be sufficient?

Irp = NULL;
IoAcquireCancelSpinLock(&CancelIrql); <=== CHANGED
if (pDE->PecIrp[Channel] == NULL) {
IrpExists = FALSE;
} else {
if (IoSetCancelRoutine(pDE->PecIrp[Channel], NULL) == NULL) {
/*
* The cancel routine was called. So allow the cancel routine to complete
* the IRP.
*/
IrpExists = FALSE;
} else {
Irp = InterlockedExchangePointer(&pDE->PecIrp[Channel], NULL);
IrpExists = TRUE;
}
}

IoReleaseCancelSpinLock(CancelIrql); <=== CHANGED

___________________

The cancel routine itself is like follows:

IrpFreed = FALSE;
if (Irp == InterlockedCompareExchangePointer(pDE->PecIrp, NULL, Irp)) {
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoReleaseCancelSpinLock(Irp->CancelIrql);

/*
* Never call IoCompleteRequest while holding a spin lock.
* Attempting to complete an IRP while holding a spin lock
* can cause deadlocks.
*/
IoCompleteRequest(Irp, IO_NO_INCREMENT);

IrpFreed = TRUE;
break;
}

Now at both places the cancel spinlock protects all accesses...

Frank
  Reply With Quote
5 11th July 14:30
alexander grigoriev
External User
 
Posts: 1
Default remove cancel routine of IRP


Make sure to handle the case when InterlockedCompareExchangePointer didn't
succeed (you still have to release the spinlock andcomplete that IRP). I
don't see why you should check the function's success at all.
  Reply With Quote
6 11th July 14:30
frank van eijkelenburg
External User
 
Posts: 1
Default remove cancel routine of IRP


Thanks for your comments. The cancel routine also releases the cancel spinlock if the InterlockedCompareExchangePointer didn't succeed (but the
snippet of code was too short). The reason why I check if the return value of InterlockedCompareExchangePointer is equal to the Irp is to make sure I
handle the right Irp.
  Reply With Quote


  sponsored links


Reply


Thread Tools
Display Modes




Copyright © 2006 SmartyDevil.com - Dies Mies Jeschet Boenedoesef Douvema Enitemaus -
666