Greetings!

I call the following function from my NDIS protocol unload handler:

APIRET Cleanup(VOID)
{
NTSTATUS status;
LARGE_INTEGER liTimeout;

SignalEvent(hTerminateThread);
//
// In NT kernel mode, we must wait for the thread
// itself to terminate. Otherwise we will unload
// while the thread is still active. => KABOOM!
//
PAGED_CODE();
ASSERT(hThread != 0);
liTimeout.QuadPart = -10000000LL; // Wait one second
status = KeWaitForSingleObject(hThread,
Executive,
KernelMode,
FALSE,
&liTimeout);
// Close handle, we'll not be using it anymore.
ZwClose(hThread);
hThread = 0;
DestroyHashTable(hHashTable);

return APIRET_OK;
}

This results in an IRQL_NOT_LESS_OR_EQUAL exception with the following
params:

Arg1: 80000548, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000000, value 0 = read operation, 1 = write operation
Arg4: 804ea528, address which referenced memory

READ_ADDRESS: 80000548
CURRENT_IRQL: 2
FAULTING_IP:
nt!KeWaitForSingleObject+b9
804ea528 803b02 cmp byte ptr [ebx],0x2

Which I find a bit puzzling. The "Memory referenced" argument is the
same as the value of hThread. hThread was created at the init of the
driver by PsCreateThread.

As you can see, both the PAGED_CODE() macro and the ASSERT for checking
the thread handle is passed successfully.

This is on a plain Windows XP Professional GA with no fixes btw... Just
to have a clean test environment.

Is there any other preferred way to do this, or any obvious mistakes
that I've done with regards to KeWaitForSingleObject? I have tried not
waiting too, but that traps when the sleeping thread wakes up after the
driver image has been unloaded... :/

Take Care!
Harald Eilertsen!

Re: Terminating threads at protocol unload time (NDIS) by Calvin

Calvin
Tue May 04 10:08:33 CDT 2004

It should be waiting on the thread OBJECT instead of a thread HANDLE. The
thread object can be obtained from ObReferenceObjectByHandle.

Can you post the full stack backtrace instead of one single frame?

Calvin
-
Calvin Guan Software Engineer
ATI Technologies Inc. www.ati.com

"Harald Eilertsen" <haraldei@anduin.net> wrote in message
news:c77lqg$rjs$1@services.kq.no...
> Greetings!
>
> I call the following function from my NDIS protocol unload handler:
>
> APIRET Cleanup(VOID)
> {
> NTSTATUS status;
> LARGE_INTEGER liTimeout;
>
> SignalEvent(hTerminateThread);
> //
> // In NT kernel mode, we must wait for the thread
> // itself to terminate. Otherwise we will unload
> // while the thread is still active. => KABOOM!
> //
> PAGED_CODE();
> ASSERT(hThread != 0);
> liTimeout.QuadPart = -10000000LL; // Wait one second
> status = KeWaitForSingleObject(hThread,
> Executive,
> KernelMode,
> FALSE,
> &liTimeout);
> // Close handle, we'll not be using it anymore.
> ZwClose(hThread);
> hThread = 0;
> DestroyHashTable(hHashTable);
>
> return APIRET_OK;
> }
>
> This results in an IRQL_NOT_LESS_OR_EQUAL exception with the following
> params:
>
> Arg1: 80000548, memory referenced
> Arg2: 00000002, IRQL
> Arg3: 00000000, value 0 = read operation, 1 = write operation
> Arg4: 804ea528, address which referenced memory
>
> READ_ADDRESS: 80000548
> CURRENT_IRQL: 2
> FAULTING_IP:
> nt!KeWaitForSingleObject+b9
> 804ea528 803b02 cmp byte ptr [ebx],0x2
>
> Which I find a bit puzzling. The "Memory referenced" argument is the
> same as the value of hThread. hThread was created at the init of the
> driver by PsCreateThread.
>
> As you can see, both the PAGED_CODE() macro and the ASSERT for checking
> the thread handle is passed successfully.
>
> This is on a plain Windows XP Professional GA with no fixes btw... Just
> to have a clean test environment.
>
> Is there any other preferred way to do this, or any obvious mistakes
> that I've done with regards to KeWaitForSingleObject? I have tried not
> waiting too, but that traps when the sleeping thread wakes up after the
> driver image has been unloaded... :/
>
> Take Care!
> Harald Eilertsen!



Re: Terminating threads at protocol unload time (NDIS) by Harald

Harald
Wed May 05 03:52:58 CDT 2004

Calvin Guan wrote:

> It should be waiting on the thread OBJECT instead of a thread HANDLE. The
> thread object can be obtained from ObReferenceObjectByHandle.

Ah... Thank you! That did the trick!

> Can you post the full stack backtrace instead of one single frame?

You still want it? I can reproduce it again, but if you don't need it I
won't bother.

Best regards,
Harald Eilertsen
Norman ASA