0

I'm trying to write IOCP server with C# using Win32API, imported from kernel32.dll and ws2_32.dll.

The problem occurs within worker threads. If I make frequent request to the server, it dies within a ten seconds. (break the loop!) Detailed situation is, after GetQueuedCompletionStatus() function returns false, returned integer pointer lpOverlapped is NULL, and GetLastWin32Error() returns code 735, which is ERROR_ABANDONED_WAIT_0.

The error is described in msdn as follow:

If a call to GetQueuedCompletionStatus fails because the completion port handle associated with it is closed while the call is outstanding, the function returns FALSE, *lpOverlapped will be NULL, and GetLastError will return ERROR_ABANDONED_WAIT_0.

But when I debugged the program, completionPort variable was valid and it doesn't seems like completion port has been closed. please take a look at the code.

public int WorkerThread()
{       
    ...
    while (true) {
        // Wait until all socket I/O completes.
        bool ret = GetQueuedCompletionStatus(
            completionPort: completionPort,
            lpNumberOfBytesTransferred: out bytesTransferred,
            lpCompletionKey: out intPtrPerHandleData,
            lpOverlapped: out intPtrOverlapped,
            dwMilliseconds: uint.MaxValue);

        // WHAT IS WRONG!?!??!
        if (intPtrOverlapped == IntPtr.Zero)
        {
            Logger.ErrorLog();
            break;
        }

        // Recover PerIoData and PerHandleData from IntPtr
        ...

        // Disconnected from client.
        if (ret == false && bytesTransferred == 0) {
            socketRefCount[perHandleData.Socket]--;
            if (socketRefCount[perHandleData.Socket] == 0)
            {
                socketRefCount.Remove(perHandleData.Socket);
                perHandleData.Socket.Close();
            }
            gchPerHandleData.Free();
            gchPerIoData.Free();
        }
    }
}

I thought completion port was O.K., so I first changed the break clause to continue. Then it makes 735 error (ERROR_ABANDONED_WAIT_0) first, and then infinitely makes error code 6 (WSA_INVALID_HANDLE). Following is simplified log.

Thread[4] : Error[735]
Thread[5] : Error[735]
Thread[7] : Error[735]
Thread[6] : Error[735]
Thread[4] : Error[6]
Thread[5] : Error[6]
Thread[7] : Error[6]
Thread[6] : Error[6]
Thread[4] : Error[6]
Thread[5] : Error[6]
...

So there IS a problem with completion port, right? Can you explain what is the problem I've encountered with and possible cause to this problem? (I just made about ten to twenty of 50 bytes messages per second. I think it is very few, but server fails to afford it even for a minute!) Do I have to reconstruct I/O completion port and worker threads every time this error occurs? (i.e. reset the server?)

--- Update! Added full version of worker thread code: http://ideone.com/J0flmC

Jongbin Park
  • 659
  • 6
  • 14

0 Answers0