views:

22

answers:

1

The program runs fine for a few minutes and then ReadFile starts failing with error code ERROR_WORKING_SET_QUOTA.

I'm using ReadFile with overlapped I/O like so:

while (continueReading)
{
    BOOL bSuccess = ReadFile(deviceHandle, pReadBuf, length, 
                             &bytesRead, readOverlappedPtr);
    waitVal = WaitForMultipleObjects(
                (sizeof(eventsToWaitFor)/sizeof(eventsToWaitFor[0])), 
                eventsToWaitFor, FALSE, INFINITE);
    if (waitVal == WAIT_OBJECT_0) {
       // do stuff
    } else if (waitVal == WAIT_OBJECT_0 + 1) {
       // do stuff
    } else if (waitVal == WAIT_OBJECT_0 + 2) {
       // complete the read
       bSuccess = GetOverlappedResult(deviceHandle, &readOverlapped, 
                                      &bytesRead, FALSE);
       if (!bSuccess) {
          errorCode = GetLastError();
          printf("ReadFile error=%d\n", errorCode);
       }
    }
}

Why am I getting this error?

A: 

The problem is that ReadFile is getting called more times than GetOverlappedResult. Causing the process to run out of resources for dealing with all the outstanding reads.

Additionally, we should check the result of ReadFile and ensure the result is ERROR_IO_PENDING, if it isn't and ReadFile returned FALSE then there is another problem.

Ensure that GetOverlappedResult is called once for each call to ReadFile. Like so:

BOOL bPerformRead = TRUE;
while (continueReading) 
{ 
    BOOL bSuccess = TRUE;
    // only perform the read if the last one has finished
    if (bPerformRead) {
       bSuccess = ReadFile(deviceHandle, pReadBuf, length,
                           &bytesRead, readOverlappedPtr);
       if (!bSuccess) {
          errorCode = GetLastError();
          if (errorCode != ERROR_IO_PENDING) {
             printf("ReadFile error=%d\n", errorCode); 
             return;
          }
       } else {
          // read completed right away
          continue;
       }
       // we can't perform another read until this one finishes
       bPerformRead = FALSE;
    }
    waitVal = WaitForMultipleObjects( 
                (sizeof(eventsToWaitFor)/sizeof(eventsToWaitFor[0])),  
                eventsToWaitFor, FALSE, INFINITE); 
    if (waitVal == WAIT_OBJECT_0) { 
       // do stuff 
    } else if (waitVal == WAIT_OBJECT_0 + 1) { 
       // do stuff 
    } else if (waitVal == WAIT_OBJECT_0 + 2) { 
       // complete the read 
       bSuccess = GetOverlappedResult(deviceHandle, &readOverlapped,  
                                      &bytesRead, FALSE); 
       // the read is finished, we can read again
       bPerformRead = TRUE;
       if (!bSuccess) { 
          errorCode = GetLastError(); 
          printf("GetOverlappedResult from ReadFile error=%d\n", errorCode); 
       } 
    } 
} 
Tom
Closer. But actually verifying that ReadFile returns FALSE and GetLastError() returns ERROR_IO_PENDING is *very* important. Reading files often completes immediately when the data comes out of the file system cache.
Hans Passant
Thanks, updated to incorporate your suggestions.
Tom