Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Why does 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?

240 views
Skip to first unread message

allswellthatendswell

unread,
Jan 4, 2016, 8:00:18 AM1/4/16
to
{ 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;

// try
// {
// CLogFile* pLogFile = new
CLogFile(L"SmartCamXi_NVR_Recorder.log", TRUE);
// if(pLogFile != NULL)
// {
// TCHAR tmp[MAX_PATH];
// _stprintf(tmp, L"Ignoring P Frames -
I Frame Interval is not set correctly - CameraControlLib: Camera ID: %d,
Expected I Frame Interval: %d \n", m_nCameraID, m_nMaxFrames - 2);
// pLogFile->Write(tmp);
// delete pLogFile;
// }
// }
// catch (...)
// {
// }

// m_nPFramesIgnored = 0;
//}
return false;
}
}

return true;
}


//==========================================================================
======================
void CDataTransferServer::SetNewDataEvents()
{
DWORD dwNow = ::GetTickCount();
unsigned int nRemoveThisID = 0xffffffff;
#ifndef LINUX
::EnterCriticalSection(&m_lockEvents);
#else
pthread_mutex_lock(&m_lockEvents);
#endif
CUserEventMap::iterator itEvent = m_mapUserEvents.begin();
while (itEvent != m_mapUserEvents.end())
{
// Check to see if the previous event has been consumed
if (::WaitForSingleObject(itEvent->second.hEvent, 0) ==
WAIT_OBJECT_0)
{
// It hasn't -- make sure it hasn't been inactive for too
long
DWORD dwElapsed;
if (itEvent->second.nLastEventConsumedTime == 0)
{
// This event hasn't been set yet, so don't try to
check the time
dwElapsed = 0;
}
else if (dwNow >= itEvent->second.nLastEventConsumedTime)
dwElapsed = dwNow -
itEvent->second.nLastEventConsumedTime;
else
{
// The time wrapped around back to 0.
dwElapsed = 0xffffffff -
itEvent->second.nLastEventConsumedTime + dwNow;
}

if (dwElapsed > 300000) // 5 minute timeout
nRemoveThisID = itEvent->first;
}
else
itEvent->second.nLastEventConsumedTime = dwNow;

::SetEvent(itEvent->second.hEvent);
++itEvent;
}

// Remove one user if the event has timed out. This will only remove
one user each
// time in this function, but this is called frequently.
if (nRemoveThisID != 0xffffffff)
RemoveUser(nRemoveThisID);
#ifndef LINUX
::LeaveCriticalSection(&m_lockEvents);
#else
pthread_mutex_lock(&m_lockEvents);
#endif

}





extern "C"
{
int func() /* THIS IS WHERE THE PROBLEM IS */
{
wchar_t memoryName[256];
wchar_t mutexName[256];
wchar_t eventName[256];
mbstowcs(memoryName, "MemoryName", 256);
mbstowcs(mutexName, "MutexName", 256);
mbstowcs(eventName, "EventName", 256);
std::wstring memoryString(memoryName);
std::wstring mutexString(mutexName);
std::wstring eventString(eventName);
CDataTransferServer *srv = new CDataTransferServer();
srv->Initialize(1, CC_SAMPLETYPE_MPEG4,128,256,64);
printf("Inside entry point tester 1\n");
srv->AddUser(5, memoryString, mutexString, eventString);
printf("Inside entry point tester 2\n");
delete srv;
printf("Exiting entry point tester \n");

/* THIS IS WHERE THE PROBLEM IS */

}
}


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Francis Glassborow

unread,
Jan 4, 2016, 11:10:18 AM1/4/16
to

On 04/01/2016 12:55, allswellthatendswell wrote:
> { 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.
>

Well I note two things in the extern "c" function

1) Its return type is NOT void
2) There is no return type


If you expect others to wade through your code looking for causes you
need first to provide code as specified.

Finally as you appear to be using a g++ extension you might get a more
informed answer in a g++ forum

Francis

Jerry Stuckle

unread,
Jan 4, 2016, 12:30:19 PM1/4/16
to
<snip code>

Normally a segfault on a function return means the stack has been
overwritten and the return address is bad. It could be anything from a
buffer overrun to insufficient stack size (shouldn't be a problem
nowadays, but I don't know what you've allocated from the stack before
arriving here). Looking through your code I don't see anything that
jumps out at me, but you've left out a lot of information.

Which compiler are you using? What compiler options? Do you have any
errors or warnings?

You didn't provide a compilable example (or even the header files), so
it's impossible for others to test. All I can recommend is to comment
out all of the code in func() and try uncommenting a couple of lines at
a time until you get the error.

--
==================
Remove the "x" from my email address
Jerry Stuckle
jstu...@attglobal.net
==================

marlow...@googlemail.com

unread,
Jan 12, 2016, 8:30:19 AM1/12/16
to

On Monday, January 4, 2016 at 1:00:18 PM UTC, allswellthatendswell wrote:
> 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.

Use valgrind.
0 new messages