Search code examples
winapireadfileoverlapped-io

Calls to ReadFile return ERROR_WORKING_SET_QUOTA


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?


Solution

  • 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 successful 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); 
           } 
        } 
    }