2012-10-10 10 views
2

내 프로그램이 멈추고 GetQueuedCompletionStatus()로 좁혀진 이유를 알아 내기 위해 tryign입니다.GetQueuedCompletionStatus hang

모든 IOCP 스레드는 고정되어 있으며 스레드가 보유한 차단 호출은 GetQueuedCompletionStatus()입니다.

GetQueuedCompletionStatus()가 실행중인 시간이 약 30 분 ~ 6 시간 후에도 계속 연결을 유지할 수있는 이유가 있습니까?

이것은 IOCP를 사용하는 TCP Winsock 프로그램입니다. OS는 Windows Server 2008 R2 Enterprise입니다.

감사합니다.

스레드 코드 :

while (TRUE) 
    { 
     pClient = NULL; 
     pOverlapped = NULL; 
     bRet = GetQueuedCompletionStatus(hCompletionPort, &dwIOLen, (LPDWORD)&pClient, (LPOVERLAPPED*)&pOverlapped, INFINITE); 
     if (bRet == true && pClient != NULL && pOverlapped != NULL && pClient->bConnected == true && pClient->bToDisconnect == false) 
     { 
      if (pOverlapped->bIOMode == 0) // Recv 
      { 
       if (TryEnterCriticalSection(&pClient->mNetworkReadCSection)) 
       { 
        pClient->dwSockBuffLength += dwIOLen; 

        // Packet processing here... 

        WSABUF pWSABuf; 
        pWSABuf.buf = (char*)&pClient->mSockBuffer[pClient->dwSockBuffLength]; 
        pWSABuf.len = 10000 - pClient->dwSockBuffLength; 
        DWORD dwRecvd; 
        DWORD dwFlags = 0; 
        memset(&pClient->mSockOverlapped, 0x00, sizeof(WSAOVERLAPPED)); 
        pClient->mSockOverlapped.bIOMode = 0; 
        int iSent = WSARecv(pClient->ClientSocket, &pWSABuf, 1, &dwRecvd, &dwFlags, (WSAOVERLAPPED*)&pClient->mSockOverlapped, NULL); 
        if (iSent == SOCKET_ERROR) 
        { 
         if (WSAGetLastError() == 10053 || WSAGetLastError() == 10054 || WSAGetLastError() == 10058) 
         { 
          //pClient->bToDisconnect = true; 
          //LeaveCriticalSection(&pClient->mNetworkReadCSection); 
          OnDissconnect(pPacketWriter, pClient->iClientID); 
          continue; 
         } 

         if (WSAGetLastError() != 997 && WSAGetLastError() != 10004 && WSAGetLastError() != 10038) 
          WriteToFile("IOCPSocketErr.txt", "[%s] Socket Error: %d\n", pClient->szPlayerName, WSAGetLastError()); 
        } 

        LeaveCriticalSection(&pClient->mNetworkReadCSection); 
       } 
       else 
       { 
        PostQueuedCompletionStatus(hCompletionPort, dwIOLen, (DWORD)pClient, (OVERLAPPED*)pOverlapped); 
       } 
      } 
      else if (pOverlapped->bIOMode == 1) // Send 
      { 
       dwBytesSent += dwIOLen; 
      } 
     } 
    } 
+0

Nop, Windows Server 2008 R2 Enterprise. – user1727542

+0

코드는 여기에 보증되어 있습니다. GQCS는 감지 된 작업이 없을 때 디자인에 따라 중단됩니다. IOCP에 등록 된 것으로 생각되는 데이터가있는 소켓은 실제로는 그렇지 않거나 다른 방법으로 이런 식으로 악의적 인 경우가 발생합니다. GQCS가 올바르게 듣고 있는지 확인하기 위해 아무 것도하지 않는 PostQCS를 발행 한 heartbeat 스레드 (테스트 용)를 넣을 수 있습니까? 당신이 그것을 이해하기를 바랍니다. – WhozCraig

+0

그러나 2000 이상의 소켓이 연결되어 있고 IOCP는 스레드가 작동하는지 여부를 확인하기 위해 별다른 이상한 소리를 내지 않습니다. – user1727542

답변

2

그것은 가장 가능성이 코드에서 버그입니다.

저는 IOCP와 GetQueuedCompletionStatus()을 10 년 넘게 사용해 왔으며 어떤 플랫폼에서도이 문제를 본 적이 없습니다.

시작에 대한

가 개인적으로 차라리 매직 넘버보다 사용 오류 상수를 참조하는 것을 선호 ... 당신의 소켓이 오류 이후에 잠겨 떠날 것이다 단절 위 LeaveCriticalSection(&pClient->mNetworkReadCSection);을 주석 나를보고하기가 어렵다 당신이 여기서 정확히 어떤 오류를 다루고 있는지.

I/O 작업이 보류 중이 아니므로 IOCP 스레드에 대한 작업이없는 상황이 발생할 것으로 예상됩니다. I/O 작업을 실행할 때 증가하는 카운터와 디버깅을 완료 할 때 증가하는 카운터를 유지할 수 있으며, 자신의 완료를 포트에 게시 할 때 증가시킵니다. 그러면 중단 된 프로그램에 침입했을 때 보류중인 I/O 작업이 있는지 확인할 수 있습니다. 카운터를 증가시키기 전에 카운터를 증가 시키십시오 (그리고 작업이 실패하면 감소시킵니다). 그렇지 않으면 증분 이전에 완료가 발생하면 카운터가 음수가 될 수 있습니다.

+0

스레드에서 각 API 호출 전후에 로그를 추가하여 어느 것이 문제인지 다시 확인했습니다. 그 경우 실제로 GetQueuedCompletionStatus() i가 카운터 검사를 구현하고 알려줍니다. 제안 해 주셔서 감사합니다. :) – user1727542

0

문서를 올바르게 읽으면 GetQueuedCompletionStatus가 false를 반환하고 pOverlapped이 NULL이 아닌 경우를 가질 수 있습니다. 아마도이 경우를 테스트하고 처리해야합니다.