Thread terminates during second ReadFile() call to My Driver

Hello All,

Can anyone have idea what could be the issues here.
Hope I explained the prblem here in readable way.

I am facing the following problem in my USB driver.
I have ReadFile() Dispatch routine and a ReadThread as follows.
I store the ReadFile() Irp in the Device Extension(ReadIrp) and
complete it later if no data immediately available in the receive
buffer. Incase of timeout also the Irp is completed.

If I make the deviceExtension->ReadIrp to NULL as in
below functions, my second ReadFile() kills the ReadThread function.
Am I making mistake here Or anything I should take care before doing so?
Any suggestion welcome. Thanks in advane.

NTSTATUS Dispatch_Read(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
// Declarations …

// initializing a device extension PIRP to null
deviceExtension->ReadIrp = NULL;

irpStack = IoGetCurrentIrpStackLocation(Irp);
lengthRequested = irpStack->Parameters.Read.Length;

// Do some checks here on the parameters…

// Create s system thread to read data from the rx data queue.
//When receiving first time ReadFile() call, thread is created
if(deviceExtension->ThreadHandle == NULL)
{
// Clear the user read complete event
KeClearEvent(&deviceExtension->UserReadEvent);

if( STATUS_SUCCESS !=
PsCreateSystemThread(
&deviceExtension->ThreadHandle,
(ACCESS_MASK) 0L,
NULL,
NULL,
NULL,
(PKSTART_ROUTINE)ReadThread,
DeviceObject))
{
// Completes the Irp with status as insuficient resources
}
}

// Check data in receive queue and return success if available
// If data available Status and Information filled up in the
// function itself.
ntStatus = PerformReadFromReceiveQueue(DeviceObject, Irp);
if(NT_SUCCESS(ntStatus))
{
// Complete the Irp. Data received. Return STATUS_SUCCESS
}

// Data not available in the queue. Mark Irp pending.
IoSetCancelRoutine(Irp, (PDRIVER_CANCEL)BtUsb_CancelRead);
IoMarkIrpPending(Irp);

// Store the Irp in device extension variable
deviceExtension->ReadIrp = Irp;

ntStatus = STATUS_PENDING;

// used in ReadThread
KeClearEvent(&deviceExtension->UserReadCompleteEvent);
// used in ReadThread
KeSetEvent(&deviceExtension->UserReadEvent, 1, FALSE);

return ntStatus; // returns STATUS_PENDING
}

// ReadThread() Funtion
void ReadThread(PDEVICE_OBJECT DeviceObject)
{
// Declarations …

deviceExtension = DeviceObject->DeviceExtension;

// Thread start
while(1)
{
// Wait for the read event to be signaled. This will be signaled
// when a ReadFile() is issued from the application
ntStatus = KeWaitForSingleObject(
&deviceExtension->UserReadEvent,
Executive,
KernelMode,
FALSE,
NULL);

// Clear the user read compplete event
KeClearEvent(&deviceExtension->UserReadEvent);

// This condition fails during second ReadFile()issue
if(deviceExtension->ReadIrp != NULL)
{
// ReadTimeout set to Xms value. Event will be SET if data
// received in parallel to the receive queue.
// otherwise timesout will cause the event to SET.
ReadTimeout.QuadPart =
((LONG)deviceExtension->ReadTimeout * -10000);
ntStatus = KeWaitForSingleObject(
&deviceExtension->UserReadCompleteEvent,
Executive,
KernelMode,
FALSE,
&ReadTimeout);

// clear the notification event
KeClearEvent(&deviceExtension->UserReadCompleteEvent);

if(deviceExtension->ReadIrp != NULL)
{
if(ntStatus != STATUS_TIMEOUT)
{
// Read data and fills up the status and information field of ReadIrp
ntStatus = PerformReadFromReceiveQueue(DeviceObject,
deviceExtension->ReadIrp);
if(ntStatus != STATUS_SUCCESS)
{
deviceExtension->ReadIrp->IoStatus.Status = STATUS_CANCELLED;
deviceExtension->ReadIrp->IoStatus.Information = 0;
}
}
else
{
deviceExtension->ReadIrp->IoStatus.Status =
STATUS_IO_TIMEOUT;
deviceExtension->ReadIrp->IoStatus.Information = 0;
}

//
IoCompleteRequest(deviceExtension->ReadIrp,
IO_NO_INCREMENT);
// Causes my thread to terminate in second ReadFile()
deviceExtension->ReadIrp = NULL;
}
else
{
break; // to kill the thread if ReadIrp is NULL
}
}
else
{
break; // // to kill the thread if ReadIrp is NULL
}
} // end while()

// Terminate the system thread which was created for reading
PsTerminateSystemThread(STATUS_SUCCESS);
}

Thanks in Advance,

  • Palani

I think you need a queue to put the IRPs for the worker thread. How can you
be sure the first one is done before the second one occurs? Checking for
STATUS_SUCCESS is not a good idea most of the time. Use the macro as you
did in another place. Driver Verifier likes to use various values for
success and that will catch you. This is NT and not DOS, so expecting all
requests to be synchronous is a very bad idea.

----- Original Message -----
From: “Palani”
To: “NT Developers Interest List”
Sent: Saturday, April 20, 2002 12:39 AM
Subject: [ntdev] Thread terminates during second ReadFile() call to My
Driver

> Hello All,
>
> Can anyone have idea what could be the issues here.
> Hope I explained the prblem here in readable way.
>
> I am facing the following problem in my USB driver.
> I have ReadFile() Dispatch routine and a ReadThread as follows.
> I store the ReadFile() Irp in the Device Extension(ReadIrp) and
> complete it later if no data immediately available in the receive
> buffer. Incase of timeout also the Irp is completed.
>
> If I make the deviceExtension->ReadIrp to NULL as in
> below functions, my second ReadFile() kills the ReadThread function.
> Am I making mistake here Or anything I should take care before doing so?
> Any suggestion welcome. Thanks in advane.
>
> NTSTATUS Dispatch_Read(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
> {
> // Declarations …
>
> // initializing a device extension PIRP to null
> deviceExtension->ReadIrp = NULL;
>
> irpStack = IoGetCurrentIrpStackLocation(Irp);
> lengthRequested = irpStack->Parameters.Read.Length;
>
> // Do some checks here on the parameters…
>
> // Create s system thread to read data from the rx data queue.
> //When receiving first time ReadFile() call, thread is created
> if(deviceExtension->ThreadHandle == NULL)
> {
> // Clear the user read complete event
> KeClearEvent(&deviceExtension->UserReadEvent);
>
> if( STATUS_SUCCESS !=
> PsCreateSystemThread(
> &deviceExtension->ThreadHandle,
> (ACCESS_MASK) 0L,
> NULL,
> NULL,
> NULL,
> (PKSTART_ROUTINE)ReadThread,
> DeviceObject))
> {
> // Completes the Irp with status as insuficient resources
> }
> }
>
> // Check data in receive queue and return success if available
> // If data available Status and Information filled up in the
> // function itself.
> ntStatus = PerformReadFromReceiveQueue(DeviceObject, Irp);
> if(NT_SUCCESS(ntStatus))
> {
> // Complete the Irp. Data received. Return STATUS_SUCCESS
> }
>
> // Data not available in the queue. Mark Irp pending.
> IoSetCancelRoutine(Irp, (PDRIVER_CANCEL)BtUsb_CancelRead);
> IoMarkIrpPending(Irp);
>
> // Store the Irp in device extension variable
> deviceExtension->ReadIrp = Irp;
>
> ntStatus = STATUS_PENDING;
>
> // used in ReadThread
> KeClearEvent(&deviceExtension->UserReadCompleteEvent);
> // used in ReadThread
> KeSetEvent(&deviceExtension->UserReadEvent, 1, FALSE);
>
> return ntStatus; // returns STATUS_PENDING
> }
>
>
> // ReadThread() Funtion
> void ReadThread(PDEVICE_OBJECT DeviceObject)
> {
> // Declarations …
>
> deviceExtension = DeviceObject->DeviceExtension;
>
> // Thread start
> while(1)
> {
> // Wait for the read event to be signaled. This will be signaled
> // when a ReadFile() is issued from the application
> ntStatus = KeWaitForSingleObject(
> &deviceExtension->UserReadEvent,
> Executive,
> KernelMode,
> FALSE,
> NULL);
>
> // Clear the user read compplete event
> KeClearEvent(&deviceExtension->UserReadEvent);
>
> // This condition fails during second ReadFile()issue
> if(deviceExtension->ReadIrp != NULL)
> {
> // ReadTimeout set to Xms value. Event will be SET if data
> // received in parallel to the receive queue.
> // otherwise timesout will cause the event to SET.
> ReadTimeout.QuadPart =
> ((LONG)deviceExtension->ReadTimeout * -10000);
> ntStatus = KeWaitForSingleObject(
> &deviceExtension->UserReadCompleteEvent,
> Executive,
> KernelMode,
> FALSE,
> &ReadTimeout);
>
> // clear the notification event
> KeClearEvent(&deviceExtension->UserReadCompleteEvent);
>
> if(deviceExtension->ReadIrp != NULL)
> {
> if(ntStatus != STATUS_TIMEOUT)
> {
> // Read data and fills up the status and information field of ReadIrp
> ntStatus = PerformReadFromReceiveQueue(DeviceObject,
> deviceExtension->ReadIrp);
> if(ntStatus != STATUS_SUCCESS)
> {
> deviceExtension->ReadIrp->IoStatus.Status = STATUS_CANCELLED;
> deviceExtension->ReadIrp->IoStatus.Information = 0;
> }
> }
> else
> {
> deviceExtension->ReadIrp->IoStatus.Status =
> STATUS_IO_TIMEOUT;
> deviceExtension->ReadIrp->IoStatus.Information = 0;
> }
>
> //
> IoCompleteRequest(deviceExtension->ReadIrp,
> IO_NO_INCREMENT);
> // Causes my thread to terminate in second ReadFile()
> deviceExtension->ReadIrp = NULL;
> }
> else
> {
> break; // to kill the thread if ReadIrp is NULL
> }
> }
> else
> {
> break; // // to kill the thread if ReadIrp is NULL
> }
> } // end while()
>
> // Terminate the system thread which was created for reading
> PsTerminateSystemThread(STATUS_SUCCESS);
> }
>
> Thanks in Advance,
> - Palani
>
> —
> You are currently subscribed to ntdev as: xxxxx@yoshimuni.com
> To unsubscribe send a blank email to %%email.unsub%%
>