Microsoft KB Archive/245434

From BetaArchive Wiki
Knowledge Base


An application may stop when you are doing serialization with the MFC CSocketFile and CArchive classes in a multiprocessor environment

Article ID: 245434

Article Last Modified on 11/21/2006



APPLIES TO

  • Microsoft Foundation Class Library 4.2, when used with:
    • Microsoft Visual C++ 2.1
    • Microsoft Visual C++ 2.2
    • Microsoft Visual C++ 4.0 Standard Edition
    • Microsoft Visual C++ 4.1 Subscription
    • Microsoft Visual C++ 4.2 Enterprise Edition
    • Microsoft Visual C++ 5.0 Enterprise Edition
    • Microsoft Visual C++ 6.0 Enterprise Edition
    • Microsoft Visual C++ 4.2 Professional Edition
    • Microsoft Visual C++ 5.0 Professional Edition
    • Microsoft Visual C++ 6.0 Professional Edition
    • Microsoft Visual C++ 6.0 Standard Edition
    • Microsoft Visual C++ 2005 Express Edition
    • Microsoft Visual C++ .NET 2003 Standard Edition
    • Microsoft Visual C++ .NET 2002 Standard Edition



This article was previously published under Q245434

Note Microsoft Visual C++ .NET 2002 and Microsoft Visual C++ .NET 2003 support both the managed code model that is provided by the Microsoft .NET Framework and the unmanaged native Microsoft Windows code model. The information in this article applies only to unmanaged Visual C++ code. Microsoft Visual C++ 2005 supports both the managed code model that is provided by the Microsoft .NET Framework and the unmanaged native Microsoft Windows code model.

SYMPTOMS

When you are doing serialization with the MFC CSocketFile and CArchive classes in a multiprocessor environment, an application may stop (hang) while it is waiting for data to be received.

CAUSE

The following are possible causes:

  • The read-ahead behavior described by the following Microsoft Knowledge Base article might cause the missing of FD_READ notification from the lower Winsock layer:

    192704 PRB: CArchive::Read Might Hang When Using CSocketFile

  • The IOCtl(FIONREAD, &nBytes) call inside the CAsyncSocket::DoCallBack class implementation of the Sockcore.cpp file in the MFC source might also be subject to possible error, because of the report of incorrect data count, as described by the following Microsoft Knowledge Base article:

192599 INFO: Avoid Data Peeking in Winsock


RESOLUTION

Avoid using serialization in network programming. For additional information and guidelines, click the article numbers below to view the articles in the Microsoft Knowledge Base:

185728 SAMPLE: MFCSocs.exe Avoids Two Common MFC Socket Mistakes


192570 MFCAsync: Message-Oriented TCP and Multithreaded Client/Server


Or, avoid data peeking by overriding the MFC CAsyncSocket::DoCallBack class implementation by performing the following steps:

  1. MF6 and ealier: On the Project menu, click Settings, and then click the General tab. Under the Microsoft Foundation Classes box, click Use MFC in a Static Library. Click the Link tab, click Customize in the Category box, and then click Force File output.

    VC .NET: Select Project, and then right-click and select Properties. Select Configuration Properties, and then on the General tab, select Use MFC in a Static Library. Select Linker, and then on the command line, type /FORCE.
  2. Append the following to your StdAfx.cpp file:

    void PASCAL CAsyncSocket::DoCallBack(WPARAM wParam, LPARAM lParam)
    {
        if (wParam == 0 && lParam == 0)
            return;
    
        // Has the socket been closed?
        CAsyncSocket* pSocket = CAsyncSocket::LookupHandle((SOCKET)wParam, TRUE);
    
        // If yes, ignore message.
        if (pSocket != NULL)
            return;
    
        pSocket = CAsyncSocket::LookupHandle((SOCKET)wParam, FALSE);
        if (pSocket == NULL)
        {
            // Must be in the middle of an Accept call.
            pSocket = CAsyncSocket::LookupHandle(INVALID_SOCKET, FALSE);
            ASSERT(pSocket != NULL);
            pSocket->m_hSocket = (SOCKET)wParam;
            CAsyncSocket::DetachHandle(INVALID_SOCKET, FALSE);
            CAsyncSocket::AttachHandle(pSocket->m_hSocket, pSocket, FALSE);
        }
    
        int nErrorCode = WSAGETSELECTERROR(lParam);
        switch (WSAGETSELECTEVENT(lParam))
        {
        case FD_READ:
            {   // Comment out the data peeking code here
                //DWORD nBytes;
                //if (!pSocket->IOCtl(FIONREAD, &nBytes))
                //  nErrorCode = WSAGetLastError();
                //if (nBytes != 0 || nErrorCode != 0)
                    pSocket->OnReceive(nErrorCode);
            }
            break;
        case FD_WRITE:
            pSocket->OnSend(nErrorCode);
            break;
        case FD_OOB:
            pSocket->OnOutOfBandData(nErrorCode);
            break;
        case FD_ACCEPT:
            pSocket->OnAccept(nErrorCode);
            break;
        case FD_CONNECT:
            pSocket->OnConnect(nErrorCode);
            break;
        case FD_CLOSE:
            pSocket->OnClose(nErrorCode);
            break;
        }
    }
                            


STATUS

This behavior is by design.


Additional query words: CSocket CAsyncSocket

Keywords: kbapi kbnetwork kbprb kbwinsock KB245434