• Why does the following C++ program , DataServer.cpp, throws a segmentat

    From allswellthatendswell@21:1/5 to All on Mon Jan 4 06:55:58 2016
    { edited by mod to shorten text lines to ~70 characters. the source
    and command lines have not been edited. -mod }

    The following C++ program , DataServer.cpp, throws a segmentation
    fault at the exit of the extern "C" function, void func(void) shown
    in the bottom of this question. I compiled this program on Ubuntu
    Linux 14.04 LTS with the g++ entry point feature.

    g++ -shared -g -fPIC -DLINUX -Wl,-soname,libdataserver.so -efunc -I /home/venkat/Downloads/waitForMultipleObjects -I /home/venkat/developmentMono/SmartCamXi_Hybrid/Include DataServer.cpp DataServerLib.cpp DataTransferClient.cpp CWinEventHandle.cpp WinEvent.cpp -lpthread -lrt

    When I run gdb ./a.out core, I get the following output: :~/Downloads/DataServerLib$ gdb ./a.out

    Reading symbols from ./a.out...done.
    [New LWP 8538]
    Core was generated by `./a.out'.
    Program terminated with signal SIGSEGV, Segmentation fault.
    #0 0x0000000000000001 in ?? ()
    (gdb) bt
    #0 0x0000000000000001 in ?? ()
    #1 0x00007ffdab79f29e in ?? ()
    #2 0x0000000000000000 in ?? ()
    (gdb) where
    #0 0x0000000000000001 in ?? ()
    #1 0x00007ffdab79f29e in ?? ()
    #2 0x0000000000000000 in ?? ()
    (gdb) list
    1 #include <stdio.h>
    2 #ifndef LINUX
    3 #include <aclapi.h>
    4 #else
    5 #include <errno.h>
    6 #endif
    7 #include "DataServer.h"
    8 #include "CameraControlDefs.h"
    9 #include <iostream>
    10 #include <unistd.h>

    I would like to find out the cause of the segmentation fault and how to possibly fix it. I have already examined the delete srv source code
    line at the end of the extern "C" function , void func(void) and the CDataTransferServer destructor appears to function properly.
    Any help is greatly appreciated.






    #include <stdio.h>
    #ifndef LINUX
    #include <aclapi.h>
    #else
    #include <errno.h>
    #endif
    #include "DataServer.h"
    #include "CameraControlDefs.h"
    #include <iostream>
    #include <unistd.h>
    #include <string.h>
    #include <sys/mman.h>
    #include <sys/types.h>
    #include <stdlib.h>
    #include <sys/stat.h> /* For mode constants */
    #include <fcntl.h> /* For O_* constants */
    #include <wchar.h>
    #include "winEmul.h"
    #ifdef LINUX
    #include <semaphore.h>
    #include <unistd.h>
    #endif
    //#include "SmartLog.h"
    #ifdef LINUX
    typedef void* PSECURITY_DESCRIPTOR;
    typedef unsigned int DWORD;
    #endif

    #ifdef LINUX
    inline int memcpy_s(void* dest, size_t numberOfElements, const void *src, size_t count)
    {
    memcpy(dest, src, count);
    return errno;
    }
    #endif

    #ifdef __LP64__
    const char service_interp[] __attribute__((section(".interp"))) = "/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2";
    #else
    const char service_interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";
    #endif


    //////////////////////////////////////////////////////////////////////////// //////////////////////
    // CDataTransferUser


    //========================================================================== ======================
    CDataTransferUser::CDataTransferUser()
    {
    m_bInitialized = false;
    m_hSharedMemory = NULL;
    m_pControl = NULL;
    m_hMutexControl = NULL;
    }


    //========================================================================== ======================
    CDataTransferUser::~CDataTransferUser()
    {
    if (m_pControl)
    {
    #ifndef LINUX
    ::UnmapViewOfFile(m_pControl);
    #else
    munmap(m_pControl,0);
    #endif
    }
    if (m_hSharedMemory)
    ::CloseHandle(m_hSharedMemory);
    if (m_hMutexControl)
    ::CloseHandle(m_hMutexControl);
    }

    // The following function initializes the supplied security descriptor
    // with a DACL that grants the Authenticated Users group GENERIC_READ,
    // GENERIC_WRITE, and GENERIC_EXECUTE access.
    //
    // The function returns NULL if any of the access control APIs fail.
    // Otherwise, it returns a PVOID pointer that should be freed by calling
    // FreeRestrictedSD() after the security descriptor has been used to
    // create the object.
    #ifdef LINUX
    void* CDataTransferUser::BuildRestrictedSD(void* pSD)
    #else
    void* CDataTransferUser::BuildRestrictedSD(PSECURITY_DESCRIPTOR pSD)
    #endif
    {
    #ifdef LINUX
    return NULL;
    #else
    DWORD dwAclLength;

    PSID pAuthenticatedUsersSID = NULL;

    PACL pDACL = NULL;
    BOOL bResult = FALSE;

    PACCESS_ALLOWED_ACE pACE = NULL;

    SID_IDENTIFIER_AUTHORITY siaNT = SECURITY_NT_AUTHORITY;

    SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;

    __try
    {
    // initialize the security descriptor
    if (!InitializeSecurityDescriptor(pSD,
    SECURITY_DESCRIPTOR_REVISION))
    {
    printf("InitializeSecurityDescriptor() failed with error %d\n",
    GetLastError());
    __leave;
    }

    // obtain a sid for the Authenticated Users Group
    if (!AllocateAndInitializeSid(&siaNT, 1,
    SECURITY_AUTHENTICATED_USER_RID, 0, 0, 0, 0, 0, 0, 0,
    &pAuthenticatedUsersSID))
    {
    printf("AllocateAndInitializeSid() failed with error %d\n",
    GetLastError());
    __leave;
    }

    // NOTE:
    //
    // The Authenticated Users group includes all user accounts that
    // have been successfully authenticated by the system. If access
    // must be restricted to a specific user or group other than
    // Authenticated Users, the SID can be constructed using the
    // LookupAccountSid() API based on a user or group name.

    // calculate the DACL length
    dwAclLength = sizeof(ACL)
    // add space for Authenticated Users group ACE
    + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)
    + GetLengthSid(pAuthenticatedUsersSID);

    // allocate memory for the DACL
    pDACL = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
    dwAclLength);
    if (!pDACL)
    {
    printf("HeapAlloc() failed with error %d\n", GetLastError());
    __leave;
    }

    // initialize the DACL
    if (!InitializeAcl(pDACL, dwAclLength, ACL_REVISION))
    {
    printf("InitializeAcl() failed with error %d\n",
    GetLastError());
    __leave;
    }

    // add the Authenticated Users group ACE to the DACL with
    // GENERIC_READ, GENERIC_WRITE, and GENERIC_EXECUTE access
    if (!AddAccessAllowedAce(pDACL, ACL_REVISION,
    GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,
    pAuthenticatedUsersSID))
    {
    printf("AddAccessAllowedAce() failed with error %d\n",
    GetLastError());
    __leave;
    }

    // set the DACL in the security descriptor
    if (!SetSecurityDescriptorDacl(pSD, TRUE, pDACL, FALSE))
    {
    printf("SetSecurityDescriptorDacl() failed with error %d\n",
    GetLastError());
    __leave;
    }

    bResult = TRUE;

    } __finally
    {
    if (pAuthenticatedUsersSID)
    FreeSid(pAuthenticatedUsersSID);
    }

    if (bResult == FALSE)
    {
    if (pDACL)
    HeapFree(GetProcessHeap(), 0, pDACL);
    pDACL = NULL;
    }

    return (void*) pDACL;
    #endif // ends Windows code
    }

    // The following function frees memory allocated in the
    // BuildRestrictedSD() function
    void CDataTransferUser::FreeRestrictedSD(void* ptr)
    {
    #ifndef LINUX
    if (ptr)
    HeapFree(GetProcessHeap(), 0, ptr);
    #endif
    return;
    }



    //////////////////////////////////////////////////////////////////////////// //////////////////////
    // CDataTransferServer


    //========================================================================== ======================
    CDataTransferServer::CDataTransferServer()
    {
    m_nCameraID = 0;
    m_nFileMapSize = 0;
    m_nMaxFrames = 0;
    m_nMaxConfigSize = 0;
    m_nConfigBlocks = 0;
    m_bKeyBlock = false;
    m_nMaxDataSize = 0;
    m_nControlSize = 0;
    m_nUserReferenceCount = 0;
    m_szObjNameSuffix[0] = '\0';
    m_nLastSendTime = 0;
    m_nDistanceFromKeyData = 0;
    m_nLastErrorLoggedIgnoreFrames = 0;
    m_nPFramesIgnored = 0;
    #ifndef LINUX
    ::InitializeCriticalSectionAndSpinCount(&m_lockEvents, 0x80000400);
    #else
    pthread_mutexattr_t mutexattr;
    pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE_NP);
    pthread_mutex_init(&m_lockEvents,&mutexattr);
    #endif
    }


    //========================================================================== ======================
    CDataTransferServer::~CDataTransferServer()
    {
    // Close all of the events
    #ifndef LINUX
    ::EnterCriticalSection(&m_lockEvents);
    #else
    pthread_mutex_lock(&m_lockEvents);
    #endif
    while (m_mapUserEvents.size() > 0)
    {
    ::CloseHandle(m_mapUserEvents.begin()->second.hEvent);
    printf("before m_mapUserEvents erase size() = %d\n",m_mapUserEvents.size());
    m_mapUserEvents.erase(m_mapUserEvents.begin());
    printf("after m_mapUserEvents erase size() = %d\n",m_mapUserEvents.size());
    }
    #ifndef LINUX
    ::LeaveCriticalSection(&m_lockEvents);
    #else
    pthread_mutex_unlock(&m_lockEvents);
    printf("pthread_mutex_unlock\n");
    #endif
    #ifndef LINUX
    ::DeleteCriticalSection(&m_lockEvents);
    #else
    pthread_mutex_destroy(&m_lockEvents);
    printf("pthread_mutex_destroy\n");
    #endif
    }


    //========================================================================== ======================
    bool CDataTransferServer::AddUser(unsigned int nUserID, std::wstring& strMemoryName,
    std::wstring& strMutexName, std::wstring& strEventName)
    {
    printf("AddUser\n");
    #ifndef LINUX
    ::EnterCriticalSection(&m_lockEvents);
    #else
    pthread_mutex_lock(&m_lockEvents);
    #endif
    if (m_mapUserEvents.find(nUserID) == m_mapUserEvents.end())
    {

    ++m_nUserReferenceCount;
    UserEventInfo ei;
    ei.strEventName = L"Global\\SmartCamEvent";
    #ifdef LINUX
    wchar_t arg[512];
    mbstowcs(arg,m_szObjNameSuffix,512);
    ei.strEventName += arg;
    #else
    ei.strEventName += m_szObjNameSuffix;
    #endif
    printf("AddUser2\n");
    #ifdef LINUX
    wchar_t szUserID[16];
    swprintf(szUserID, sizeof(szUserID) / sizeof(*szUserID) ,
    L"_%x", nUserID);
    ei.strEventName += szUserID;
    #else
    TCHAR szUserID[16];
    wsprintf(szUserID, L"_%x", nUserID);
    ei.strEventName += szUserID;
    #endif
    #ifndef LINUX
    SECURITY_ATTRIBUTES sa;
    LPSECURITY_ATTRIBUTES lpEventAttributes = &sa;
    SECURITY_DESCRIPTOR sd;
    sa.nLength = sizeof sa;
    sa.bInheritHandle = FALSE;
    sa.lpSecurityDescriptor = &sd;
    void* pDACL = BuildRestrictedSD(&sd);
    if (pDACL == NULL)
    lpEventAttributes = NULL;
    ei.hEvent = CreateEvent(lpEventAttributes, FALSE, FALSE, ei.strEventName.c_str());
    #else
    ei.hEvent = CreateEvent(NULL, false, false, ei.strEventName.c_str());
    printf("AddUser3\n");
    #endif
    ei.nLastEventConsumedTime = 0;

    #ifndef LINUX
    if (pDACL)
    FreeRestrictedSD(pDACL);
    #endif

    m_mapUserEvents[nUserID] = ei;
    }

    strEventName = m_mapUserEvents[nUserID].strEventName;
    strMemoryName = m_strMemoryName;
    strMutexName = m_strMutexName;
    printf("AddUser4\n");
    #ifndef LINUX
    ::LeaveCriticalSection(&m_lockEvents);
    #else
    pthread_mutex_unlock(&m_lockEvents);
    #endif
    return true;
    }


    //========================================================================== ======================
    bool CDataTransferServer::RemoveUser(unsigned int nUserID)
    {
    #ifndef LINUX
    ::EnterCriticalSection(&m_lockEvents);
    #else
    pthread_mutex_lock(&m_lockEvents);
    #endif

    CUserEventMap::iterator itEvent = m_mapUserEvents.find(nUserID);
    if (itEvent != m_mapUserEvents.end())
    {
    if (m_nUserReferenceCount > 0)
    --m_nUserReferenceCount;

    ::CloseHandle(itEvent->second.hEvent);
    m_mapUserEvents.erase(itEvent);
    }

    #ifndef LINUX
    ::LeaveCriticalSection(&m_lockEvents);
    #else
    pthread_mutex_unlock(&m_lockEvents);
    #endif
    return true;

    }


    //========================================================================== ======================
    bool CDataTransferServer::Initialize(int nCameraID, CC_SAMPLETYPE
    nDataType,
    unsigned
    int nImageWidth, unsigned int nImageHeight,
    unsigned
    int nMaxFrames)
    {
    bool bOkay = true;
    char buffer[64] = {0};

    // This is going to be a problem if we try to re-initialize with a different image size...
    if (m_bInitialized)
    return true;


    m_nCameraID = nCameraID;
    m_nMaxFrames = nMaxFrames;
    if (m_nMaxFrames < 2)
    m_nMaxFrames = 2;

    // Calculate how much space we need for the data and headers
    m_nMaxDataSize = 0;
    m_nMaxConfigSize = 0;
    m_nConfigBlocks = 0;
    if (((nDataType & CC_SAMPLETYPE_MPEG4) == CC_SAMPLETYPE_MPEG4) || ((nDataType & CC_SAMPLETYPE_MPEG4AVC) == CC_SAMPLETYPE_MPEG4AVC))
    {
    m_nMaxDataSize = (nImageWidth * nImageHeight) + 1024; // for VideoFrame size and motion data
    m_nMaxConfigSize = 1024;
    m_nConfigBlocks = 1;
    m_bKeyBlock = true;
    }
    else if (nDataType == CC_SAMPLETYPE_UNCOMPRESSEDVIDEO_YUY2)
    {
    m_nMaxDataSize = (nImageWidth * nImageHeight * 2) + 1024; //
    for VideoFrame size and motion data
    m_nMaxConfigSize = 0;
    }
    else if (nDataType == CC_SAMPLETYPE_MJPEG)
    {
    m_nMaxDataSize = (nImageWidth * nImageHeight) + 1024; // for VideoFrame size and motion data
    m_nMaxConfigSize = 0;
    }

    m_nMaxFrames += m_bKeyBlock ? 1 : 0;
    m_nMaxDataSize += 4 + sizeof(uTypeSpecificSize);

    m_nControlSize = sizeof(CDataTransferControl);
    // Control Block
    m_nControlSize += (m_nMaxFrames - 1) *
    sizeof(CDataTransferBlockHeader); // Data Block Headers
    if (m_nMaxConfigSize > 0)
    m_nControlSize += sizeof(CDataTransferBlockHeader);

    // Make sure the control size is DWORD-aligned
    while ((m_nControlSize & 0x03) != 0)
    ++m_nControlSize;

    m_nFileMapSize = m_nControlSize + m_nMaxFrames * m_nMaxDataSize;
    // Data Blocks
    if (m_nMaxConfigSize > 0)
    m_nFileMapSize += m_nMaxConfigSize;
    // Config Header & Config Data

    // Suffix for global objects (file map and sync objects) based on
    camera ID and data type

    #ifdef LINUX
    sprintf(m_szObjNameSuffix, "_%x_%x", nCameraID, nDataType);
    #else
    ::swprintf_s(m_szObjNameSuffix, 31, L"_%x_%x", nCameraID,
    nDataType);
    #endif

    #ifndef LINUX
    SECURITY_ATTRIBUTES sa;
    SECURITY_DESCRIPTOR sd;
    sa.nLength = sizeof sa;
    sa.bInheritHandle = FALSE;
    sa.lpSecurityDescriptor = &sd;
    void* pDACL = BuildRestrictedSD(&sd);
    if (pDACL == NULL)
    bOkay = false;
    #endif
    if (bOkay)
    {
    if (m_hMutexControl == NULL)
    {
    m_strMutexName = L"Global\\SmartCamMutex";
    #ifdef LINUX
    m_hMutexControl = sem_open(buffer, O_CREAT, 0600,
    0);
    #else
    m_hMutexControl = ::CreateMutex(&sa, TRUE, m_strMutexName.c_str());
    #endif
    if (m_hMutexControl == NULL)
    bOkay = false;
    }
    }
    #ifdef LINUX
    if (bOkay)
    {
    char buffer[256];
    wcstombs(buffer,m_strMemoryName.c_str(),256);
    FILE* stream = fopen(buffer, "rw");
    int fd = fileno(stream);
    m_pControl = (CDataTransferControl*)mmap(NULL, m_nFileMapSize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    if (m_pControl)
    {
    memset(m_pControl, 0, m_nControlSize);
    m_pControl->nConfigurationBlock = 0xffffffff;
    m_pControl->nNewestKeyDataBlock = 0xffffffff;
    m_pControl->nNewestDataBlock = 0xffffffff;
    m_pControl->nBlockHeaders = m_nMaxFrames +
    m_nConfigBlocks;
    m_pControl->nTimeOfLastClientAccess = ::GetTickCount();
    }
    else
    bOkay = false;

    }
    #else
    if (bOkay)
    {
    if (m_hSharedMemory == NULL || m_hSharedMemory == INVALID_HANDLE_VALUE)
    {
    m_strMemoryName = L"Global\\SmartCamMem";
    m_strMemoryName += m_szObjNameSuffix;
    #ifdef LINUX
    m_hSharedMemory =
    #else
    m_hSharedMemory =
    ::CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE,
    #endif
    0,, m_strMemoryName.c_str());
    if (m_hSharedMemory == NULL || m_hSharedMemory == INVALID_HANDLE_VALUE)
    bOkay = false;
    }
    }
    if (bOkay)
    {
    if (m_pControl == NULL)
    {
    m_pControl = (CDataTransferControl*)::MapViewOfFile(m_hSharedMemory,

    FILE_MAP_ALL_ACCESS, 0, 0, m_nFileMapSize);
    if (m_pControl)
    {
    ::ZeroMemory(m_pControl, m_nControlSize);
    m_pControl->nConfigurationBlock = 0xffffffff;
    m_pControl->nNewestKeyDataBlock = 0xffffffff;
    m_pControl->nNewestDataBlock = 0xffffffff;
    m_pControl->nBlockHeaders = m_nMaxFrames + m_nConfigBlocks;
    m_pControl->nTimeOfLastClientAccess = ::GetTickCount();
    }
    else
    bOkay = false;
    }
    }
    #endif

    #ifndef LINUX
    if (pDACL)
    FreeRestrictedSD(pDACL);
    #endif
    if (m_hMutexControl)
    #ifndef LINUX
    ::ReleaseMutex(m_hMutexControl);
    #endif
    m_bInitialized = bOkay;

    return bOkay;
    }


    //===========================================================:============== =======================
    bool CDataTransferServer::SendData(CVideoFrame *frame)
    {
    bool bFrameSent = false;

    if (!m_bInitialized) return false;
    if(frame == NULL) return false;

    static DWORD dwWaitTime = 0;
    static DWORD dwFramesSent = 0;
    static DWORD dwFramesSkipped = 0;
    bool bShowStats = false;

    if (frame->GetSize() > m_nMaxDataSize)
    {
    #ifndef LINUX
    ::OutputDebugString(L"CDataTransferServer::SendData: Data
    exceeds available size; data not posted to memory\n");
    #else
    cerr << "CDataTransferServer::SendData: Data exceeds available size; data not posted to memory" << endl;
    #endif
    return false;
    }

    if (CheckPFrameCount(frame) == false)
    return false;

    // Wait for up to 25ms to lock the memory. That's a little shorter
    than 1/30th of a
    // second, which is our fastest video frame rate.
    DWORD dwTimeStart = ::GetTickCount();
    DWORD dwWait = ::WaitForSingleObject(m_hMutexControl, 25);
    #ifndef LINUX
    if (dwWait == WAIT_OBJECT_0 || dwWait == WAIT_ABANDONED)
    #else
    if (dwWait == WAIT_OBJECT_0)
    #endif
    {
    DWORD dwTimeNow = ::GetTickCount();
    dwWaitTime += dwTimeNow - dwTimeStart;
    ++dwFramesSent;
    bShowStats = (dwTimeNow - dwTimeStart != 0);
    unsigned long nBlock, nOffset;
    bool bOkayToSendFrame = true;
    unsigned long nNormalStartBlock = m_nConfigBlocks +
    (m_bKeyBlock ? 1 : 0);
    bool bCurrentKeyBlock = false;

    // Wrap this section in try/except to handle exceptions thrown
    by memory mapped file access
    #ifndef LINUX
    __try
    #else
    try
    #endif
    {
    if (frame->GetType() == CC_SAMPLETYPE_MPEG4_CONFIG || frame->GetType() == CC_SAMPLETYPE_MPEG4AVC_CONFIG)
    {
    // Configuration data is always in block 0
    nBlock = 0;
    nOffset = 0;
    m_pControl->nConfigurationBlock = nBlock;
    }
    else if ((frame->GetType() == CC_SAMPLETYPE_MPEG4_IFRAME
    || frame->GetType() == CC_SAMPLETYPE_MPEG4AVC_IFRAME) && m_bKeyBlock)
    {
    // Key data is always in the block after the configuration block
    // This block will be overwritten even if somebody
    is using it. We should get
    // key data infrequently enough so that this won't
    be a problem.
    bCurrentKeyBlock = true;
    nBlock = m_nConfigBlocks;
    nOffset = m_nMaxConfigSize + (nBlock - m_nConfigBlocks) * m_nMaxDataSize;
    m_pControl->nNewestKeyDataBlock = nBlock;
    m_pControl->nNewestDataBlock = nBlock;
    m_pControl->nTimeOfNewestKeyDataBlock = dwTimeNow;
    m_pControl->nTimeOfNewestDataBlock = dwTimeNow;
    }
    else
    {
    // Normal data -- get the next block that is not
    being read
    bool bContinue = true;
    nBlock = m_pControl->nNewestDataBlock;
    unsigned long nStartBlock = nBlock;

    do
    {
    if (m_pControl->nNewestDataBlock ==
    0xffffffff) // First block?
    {
    nBlock = nNormalStartBlock;
    bContinue = false;
    }
    else
    {
    ++nBlock;
    if (m_bKeyBlock && nBlock < nNormalStartBlock || nBlock >= m_nMaxFrames + m_nConfigBlocks)
    nBlock = nNormalStartBlock;
    }

    if (m_pControl->aBlockHeaders[nBlock].nReaderReferenceCount == 0)
    bContinue = false;
    else
    {
    // This block is being read. Make sure that the reader didn't timeout
    static const DWORD nReaderTimeout =
    30000;
    DWORD dwElapsed;
    if (dwTimeNow >= m_pControl->aBlockHeaders[nBlock].nTimeOfLastRead)
    dwElapsed = dwTimeNow - m_pControl->aBlockHeaders[nBlock].nTimeOfLastRead;
    else
    {
    // The time wrapped around back
    to 0.
    dwElapsed = 0xffffffff - m_pControl->aBlockHeaders[nBlock].nTimeOfLastRead + dwTimeNow;
    }

    if (dwElapsed > nReaderTimeout)
    {
    // Read timed out, so we'll use
    this block

    m_pControl->aBlockHeaders[nBlock].nReaderReferenceCount = 0;
    #ifndef LINUX

    ::OutputDebugString(L"CDataTransferServer: Releasing a block that was locked for too long.\n");
    #else
    cerr << "CDataTransferServer: Releasing a block that was locked for too long." << endl;
    #endif
    bContinue = false;
    }
    }
    } while (bContinue && nBlock != nStartBlock);

    // Did we find a good destination?
    nOffset = m_nMaxConfigSize + (nBlock - m_nConfigBlocks) * m_nMaxDataSize;
    if (m_pControl->aBlockHeaders[nBlock].nReaderReferenceCount == 0)
    {
    m_pControl->nNewestDataBlock = nBlock;
    m_pControl->nTimeOfNewestDataBlock =
    dwTimeNow;
    }
    else
    bOkayToSendFrame = false;
    }

    // actual frame sent here
    if (bOkayToSendFrame)
    {
    // Set the frame type into DataTransferControl
    m_pControl->nSampleType = frame->GetType();
    m_pControl->nDistanceFromKeyData = frame->m_nDistanceFromKeyData;
    // Set the header info for this block
    //DWORD dwTimeNow = ::GetTickCount();
    if (m_bKeyBlock)
    {
    if ((bCurrentKeyBlock) || (nBlock == m_pControl->nConfigurationBlock))
    m_nDistanceFromKeyData = 0;
    else
    ++m_nDistanceFromKeyData;
    }
    else
    { // MJPEG
    m_nDistanceFromKeyData = 0;
    }

    nOffset += m_nControlSize;


    m_pControl->aBlockHeaders[nBlock].nReaderReferenceCount = 0;

    m_pControl->aBlockHeaders[nBlock].nDistanceFromKeyData = m_nDistanceFromKeyData;

    //m_pControl->aBlockHeaders[nBlock].nDistanceFromKeyData = frame->m_nDistanceFromKeyData;
    m_pControl->aBlockHeaders[nBlock].nDataOffset = nOffset;
    m_pControl->aBlockHeaders[nBlock].nDataType = (unsigned long)frame->GetType();
    m_pControl->aBlockHeaders[nBlock].nDataSize = sizeof(DWORD) + frame->GetSize();
    m_pControl->aBlockHeaders[nBlock].nTimeOfWrite = dwTimeNow;
    m_pControl->aBlockHeaders[nBlock].nTimeOfLastRead = dwTimeNow;

    // Write an offset to the real data -- 4 bytes
    unsigned long nStartOfDataSize = 4;
    ::memcpy_s(((unsigned char*)m_pControl) + nOffset, m_nMaxDataSize, &nStartOfDataSize, nStartOfDataSize);

    nOffset += 4;

    // write frame header
    ::memcpy_s(((unsigned char*)m_pControl) + nOffset, m_nMaxDataSize, &frame->m_type, sizeof(int)); // we have it header - send it again anyway
    nOffset += sizeof(int);

    ::memcpy_s(((unsigned char*)m_pControl) + nOffset, m_nMaxDataSize, &frame->m_width, sizeof(int));
    nOffset += sizeof(int);

    ::memcpy_s(((unsigned char*)m_pControl) + nOffset, m_nMaxDataSize, &frame->m_height, sizeof(int));
    nOffset += sizeof(int);

    ::memcpy_s(((unsigned char*)m_pControl) + nOffset, m_nMaxDataSize, &frame->m_dataLength, sizeof(long));
    nOffset += sizeof(long);

    ::memcpy_s(((unsigned char*)m_pControl) + nOffset, m_nMaxDataSize, &frame->m_motionLength, sizeof(long));
    nOffset += sizeof(long);

    ::memcpy_s(((unsigned char*)m_pControl) + nOffset, m_nMaxDataSize, &frame->m_motionWidth, sizeof(long));
    nOffset += sizeof(long);

    ::memcpy_s(((unsigned char*)m_pControl) + nOffset, m_nMaxDataSize, &frame->m_motionHeight, sizeof(long));
    nOffset += sizeof(long);

    ::memcpy_s(((unsigned char*)m_pControl) + nOffset, m_nMaxDataSize, &frame->m_record, sizeof(int));
    nOffset += sizeof(int);

    // write trigger
    ::memcpy_s(((unsigned char*)m_pControl) + nOffset, m_nMaxDataSize, &frame->m_trigger, sizeof(int));
    nOffset += sizeof(int);

    ::memcpy_s(((unsigned char*)m_pControl) + nOffset, m_nMaxDataSize, &frame->m_time, sizeof(__int64));
    nOffset += sizeof(__int64);

    // write motion block
    if(frame->m_motionLength > 0)
    {
    ::memcpy_s(((unsigned char*)m_pControl) + nOffset, m_nMaxDataSize, frame->m_motion, frame->m_motionLength);
    nOffset += frame->m_motionLength;
    }

    // write data
    ::memcpy_s(((unsigned char*)m_pControl) + nOffset, m_nMaxDataSize, frame->m_data, frame->m_dataLength);
    nOffset += frame->m_dataLength;

    // we done

    bFrameSent = true;
    m_nLastSendTime = dwTimeNow;
    }
    }
    #ifndef LINUX
    __except (::GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR ?
    EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    #else
    catch(std::exception& e)
    #endif
    {
    // Access to memory mapped file caused an exception
    }

    // Updated data is ready for clients
    if (bFrameSent)
    SetNewDataEvents();
    #ifndef LINUX
    ::ReleaseMutex(m_hMutexControl);
    #else
    sem_close(m_hMutexControl);
    #endif
    }
    else
    {
    ++dwFramesSkipped;
    bShowStats = true;
    }

    if (bShowStats)
    {
    wchar_t szMsg[128];
    #ifdef LINUX
    ::swprintf(szMsg, 128, L"DataServer: %d frames sent (wait=%0.2f ms), %d frames skipped\n", dwFramesSent, dwWaitTime / (double)dwFramesSent, dwFramesSkipped);
    #else
    ::swprintf_s(szMsg, L"DataServer: %d frames sent (wait=%0.2f
    ms), %d frames skipped\n", dwFramesSent, dwWaitTime / (double)dwFramesSent, dwFramesSkipped);
    #endif
    #ifndef LINUX
    ::OutputDebugString(szMsg);
    #else
    cerr << szMsg << endl;
    #endif
    }

    return bFrameSent;
    }

    bool CDataTransferServer::CheckPFrameCount(CVideoFrame *frame)
    {
    if ((frame->GetType() == CC_SAMPLETYPE_MPEG4_PFRAME) || (frame->GetType() == CC_SAMPLETYPE_MPEG4AVC_PFRAME))
    {
    if (frame->m_nDistanceFromKeyData > (m_nMaxFrames - 2))
    // 2 = IFrame + Config Block
    { // We received more P frames than we are expecting,
    #ifndef LINUX
    ::OutputDebugString(L"CDataTransferServer::SendData: received more P frames than expected, ignoring the frames\n");
    #else
    cerr << "CDataTransferServer::SendData: received more P frames than expected, ignoring the frames" << endl;
    #endif
    m_nPFramesIgnored ++;

    //DWORD dwNow = ::GetTickCount();
    //if(dwNow - m_nLastErrorLoggedIgnoreFrames > 1000*60*60)
    // don't log too often - once in hour
    //{
    // m_nLastErrorLoggedIgnoreFrames = dwNow;


    [continued in next message]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)