Link to home
Start Free TrialLog in
Avatar of camster123
camster123

asked on

I would like to fix the Ubuntu 64 bit Linux bus error I get when trying to access the memory mapped address, m_pControl, returned by mmap.

I would like to fix the Ubuntu 64 bit Linux bus error I get when trying to access the memory mapped address, m_pControl, returned by mmap. I tried to memset it but it did not help prevent the bus error on the following source code line after memset. The Windows 7 version of this code apparently does not have a bus error.

bool CDataTransferServer::Initialize(int nCameraID,
                                     CC_SAMPLETYPE nDataType,
                                     unsigned int nImageWidth,
                                     unsigned int nImageHeight,
                                     unsigned int nMaxFrames)
{
    bool bOkay = true;
    if (m_bInitialized)
        return true;

        char buffer[256];
        m_strMemoryName = L"Global\\SmartCamMem";
                size_t origsize = strlen(m_szObjNameSuffix) + 1;
                const size_t newsize = 100;
                size_t convertedChars = 0;
                wchar_t wcstring[newsize];
                mbstowcs(wcstring, m_szObjNameSuffix,origsize);
                m_strMemoryName += wcstring;    
        wcstombs(buffer,m_strMemoryName.c_str(),256);
        int fd = open(buffer, O_CREAT | O_RDWR);
        m_pControl = fd >= 0 ? (CDataTransferControl*)mmap(NULL, m_nFileMapSize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0) : NULL;
        if (m_pControl)              
        {  
            memset(m_pControl,0x0,sizeof(m_pControl));
            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;
   return bOkay;

}


      

I would to fix the Ubuntu 64 bit Linux bus error I get when trying to access the memory mapped address, m_pControl, returned by mmap. I tried to memset it but it did not help prevent the bus error on the following source code line after memset. The Windows 7 version of this code apparently does not have a bus error.

bool CDataTransferServer::Initialize(int nCameraID,
                                     CC_SAMPLETYPE nDataType,
                                     unsigned int nImageWidth,
                                     unsigned int nImageHeight,
                                     unsigned int nMaxFrames)
{
    bool bOkay = true;
    if (m_bInitialized)
        return true;

        char buffer[256];
        m_strMemoryName = L"Global\\SmartCamMem";
                size_t origsize = strlen(m_szObjNameSuffix) + 1;
                const size_t newsize = 100;
                size_t convertedChars = 0;
                wchar_t wcstring[newsize];
                mbstowcs(wcstring, m_szObjNameSuffix,origsize);
                m_strMemoryName += wcstring;    
        wcstombs(buffer,m_strMemoryName.c_str(),256);
        int fd = open(buffer, O_CREAT | O_RDWR);
        m_pControl = fd >= 0 ? (CDataTransferControl*)mmap(NULL, m_nFileMapSize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0) : NULL;
        if (m_pControl)              
        {  
            memset(m_pControl,0x0,sizeof(m_pControl));
            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;
   return bOkay;

}

My m_pControl return value is 0x550c6000 and fd is 3.

Here is my test C++ driver program.

#include  <stdio.h>
#include  <iostream>
#include  <dlfcn.h>
#include "CameraControlDefs.h"
#include "DataServer.h"

using namespace std;


int main(int argc,char** argv)
{

   bool (*sayHello)(CDataTransferServer* _this, int nCameraID, CC_SAMPLETYPE nDataType,
                                unsigned int nImageWidth, unsigned int nImageHeight,
                                unsigned int nMaxFrames);


  unsigned int tmp;


  void* handle = dlopen("libDataServer.so", RTLD_LAZY);
  if (!handle)
  {
    std::cerr << dlerror() << std::endl;
    return 1;
  }

  // load the symbols
    create_t* create_triangle = (create_t*) dlsym(handle, "create");
    const char* dlsym_error = dlerror();
    if (dlsym_error) {
        cerr << "Cannot load symbol create: " << dlsym_error << '\n';
        return 1;
    }

    destroy_t* destroy_triangle = (destroy_t*) dlsym(handle, "destroy");
    dlsym_error = dlerror();
    if (dlsym_error) {
        cerr << "Cannot load symbol destroy: " << dlsym_error << '\n';
        return 1;
    }

    // create an instance of the class
    CDataTransferServer* poly = create_triangle();


  *(bool **)(&sayHello) = (bool *)dlsym(handle,"_ZN19CDataTransferServer10InitializeEi13CC_SAMPLETYPEjjj");
  if (dlerror())
  {
    std::cerr << dlerror() << std::endl;
    return 2;
  }


  printf("ywc = %x\n",poly);


// destroy the class

   (*sayHello)(poly, 5, CC_SAMPLETYPE_MPEG4,128,256,64);
    destroy_triangle(poly);

    // unload the triangle library
  dlclose(handle);



  return 0;

}

Please explain the bus error. Please advise on whether I should change any of the arguments to mmap or an alternate approach.
Any help is greatly appreciated.
Avatar of Duncan Roe
Duncan Roe
Flag of Australia image

Please use CODE delimiters when posting code.
Linux file names are ASCII, not UTF16.
Linux file system delimiter is /, not \
Cut out all the wide character stuff and see if it works then.
You need to provide enough code to compile  (e.g. class definition and a simple mainline to call the function) before I can help you much more.
Bus error is not generated by x86 hardware so is probably "manufactured" because there is some other problem.
Avatar of camster123
camster123

ASKER

@Duncan Roe,

Here is how I  fixed the bus error. When I execute the open instruction below , am I creating a file in disk of 0 bytes length as well as a file in random access memory of  page_size  + m_nFileMapSize + 1 bytes length?
if  (bOkay)
    {

                char buffer[256];
        m_strMemoryName = L"Global\\SmartCamMem";
                size_t origsize = strlen(m_szObjNameSuffix) + 1;
                const size_t newsize = 100;
                size_t convertedChars = 0;
                wchar_t wcstring[newsize];
                mbstowcs(wcstring, m_szObjNameSuffix,origsize);
                m_strMemoryName += wcstring;    
        wcstombs(buffer,m_strMemoryName.c_str(),256);
            unlink(buffer);
        int fd = open(buffer, O_CREAT | O_RDWR);
                printf("fd = %d\n",fd);
                int page_size = getpagesize();
                printf("result = %d\n",posix_fallocate(fd, 0, page_size + m_nFileMapSize + 1));

        m_pControl = fd >= 0 ? (CDataTransferControl*)mmap(NULL, m_nFileMapSize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0) : NULL;
             printf("m_pControl = %x\n",m_pControl);
                if (m_pControl)
        {
            memset(m_pControl, 0,sizeof(m_pControl));
            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;

    }

    if (bOkay)
    {

                char buffer[256];
        m_strMemoryName = L"Global\\SmartCamMem";
                size_t origsize = strlen(m_szObjNameSuffix) + 1;
                const size_t newsize = 100;
                size_t convertedChars = 0;
                wchar_t wcstring[newsize];
                mbstowcs(wcstring, m_szObjNameSuffix,origsize);
                m_strMemoryName += wcstring;    
        wcstombs(buffer,m_strMemoryName.c_str(),256);
            unlink(buffer);
        int fd = open(buffer, O_CREAT | O_RDWR);
                printf("fd = %d\n",fd);
                int page_size = getpagesize();
                printf("result = %d\n",posix_fallocate(fd, 0, page_size + m_nFileMapSize + 1));

        m_pControl = fd >= 0 ? (CDataTransferControl*)mmap(NULL, m_nFileMapSize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0) : NULL;
             printf("m_pControl = %x\n",m_pControl);
                if (m_pControl)
        {
            memset(m_pControl, 0,sizeof(m_pControl));
            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;

    }

Thank you.
Why do you post the same code twice?
As far as I can see, the difference between (the first half of) the 2 functions is
1,5c1
< bool CDataTransferServer::Initialize(int nCameraID,
<                                      CC_SAMPLETYPE nDataType,
<                                      unsigned int nImageWidth,
<                                      unsigned int nImageHeight,
<                                      unsigned int nMaxFrames)
---
> if  (bOkay)
7,9d2
<     bool bOkay = true;
<     if (m_bInitialized)
<         return true;
19a13
>             unlink(buffer);
20a15,18
>                 printf("fd = %d\n",fd);
>                 int page_size = getpagesize();
>                 printf("result = %d\n",posix_fallocate(fd, 0, page_size + m_nFileMapSize + 1));
> 
21a20
>              printf("m_pControl = %x\n",m_pControl);
24c23
<             memset(m_pControl,0x0,sizeof(m_pControl));
---
>             memset(m_pControl, 0,sizeof(m_pControl));
33d31
<    return bOkay;

Open in new window

The only substantive difference I can see is that you unlinked that oddly-named file. This makes the open more likely to succeed.
memset(m_pControl,0x0,sizeof(m_pControl));
is probably not doing what you want: m_pControl is a pointer so sizeof(m_pControl) is always 8 for 64-bit Ubuntu.

I just noticed, from typing man mmap in an xterm, you will get signal SIGBUS if you try to access
to a portion of the buffer that does not correspond to the file (for example,  beyond  the  end  of  the  file, including the case where another process has truncated the file).
By doing posix_fallocate(), it seems you increased the file size (which would have been zero otherwise, so of course you would get SIGBUS).
This is a "manufactured" signal as I alluded to earlier.
@Duncan Roe, Thank you for correcting my memset mistake.
May I ask  when I execute the open instruction, am I creating a file in disk of 0 bytes length as well as a file in random access memory of  page_size  + m_nFileMapSize + 1 bytes length? Thank you.
You are not creating any file in RAM. You are doing an mmap() which exceeds the size of the file. That of itself is not an error - but trying to access off the end of the mapped file is an error. The man page defines behaviour for trying to write in the last mapped page but beyond end of file - data is discarded - but for a zero-length file you are trying to write to the next page.
Hope that answers your question - post back if not.
@Duncan Roe,
   Thank you for your good comment. My manager would like to apply memory mapping to share memory between multiple client processes and a server process. Please look at this Stack Overflow URL, http://stackoverflow.com/questions/21311080/linux-shared-memory-shmget-vs-mmap and let me know your intrepretation of using shm_open + ftruncate + mmap to accomplish my manager's objective.
     Does shm_open create a file in RAM or on hard disk? Why does shm-open opens  a 0-length file in my  current working directory?
     Thank you very much.
ASKER CERTIFIED SOLUTION
Avatar of Duncan Roe
Duncan Roe
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
@Duncan Roe, If i could I award you an A Plus for  your solution which answers all my questions directly. Your solution addresses a complex technical problem in easy to understand sentences. Thank you.