1

I'm modifying a piece of CORBA software to use shared memory as a transport. I created a shared memory class that houses all the necessary calls to implement shared memory. The issue is that when I call this class in another class the shared memory is not created, but all of my methods return true as if they function correctly. Shm_open returns a non negative int (3), which indicates it didn't fail. When I replaced my class calls with hard coded shm_open inside the orb.cc class though it creates the shared memory segment.

Is this a permission issue, or is my class not just being called correctly even though all my debugging says it correctly created the segment even though it doesn't appear in /dev/shm?

Apologies on the formatting first time posting code.

Thanks in advance.

sharedMemory.cc

#include "sharedMemory.h"
#include <sys/mman.h>
#include <errno.h>
#include <cstdio>
#include <cstdlib>
#include <CORBA-SMALL.h>
#include <mico/os-net.h>
#include <semaphore.h>
#include <pthread.h>

using namespace std;

MICO::CSharedMemory::CSharedMemory( const string& sName)    :m_sName(sName),m_Ptr(NULL),m_iD(-1),
m_nSize(0)
{
m_SemiD = NULL;
}

std::string MICO::CSharedMemory::sLockSemaphoreName;

bool
MICO::CSharedMemory::openSem(std::string sem)
{
 sLockSemaphoreName = sem;

 m_SemiD = sem_open(sLockSemaphoreName.c_str(), O_CREAT, S_IRUSR | S_IWUSR,    1);
 return true;
 }

 bool
 MICO::CSharedMemory::Create( size_t nSize, int mode /*= READ_WRITE*/ )
 {
 m_nSize = nSize;
 m_iD = shm_open(m_sName.c_str(), O_CREAT | O_RDWR, 0777);

 if(m_iD < 0)
 {
  switch(errno)
  {
  case EACCES:
     throw CSharedMemoryException("Permission Exception ");
     cout << "\nEACCES";
     break;
  case EEXIST:
     cout << "\nEEXIST";
     throw CSharedMemoryException("Shared memory object specified by name already exists.");
     break;
  case EINVAL:
     cout << "\nEINVAL";
     throw CSharedMemoryException("Invalid shared memory name passed.");
     break;
  case EMFILE:
     throw CSharedMemoryException("The process already has the maximum number of files open.");
     break;
  case ENAMETOOLONG:
     throw CSharedMemoryException("The length of name exceeds PATH_MAX.");
     break;
  case ENFILE:
     throw CSharedMemoryException("The limit on the total number of files open on the system has been reached");
     break;
  default:
     cout << "\ndefault";
     throw CSharedMemoryException("Invalid exception occurred in shared memory creation");
     break;
  }
  }

 /* adjusting mapped file size (make room for the whole segment to map)      --   ftruncate() */
 ftruncate(m_iD, m_nSize);
 return true;
}

sharedMemory.h

#include <string>
#include <sys/mman.h>
#include <sys/stat.h>        /* For mode constants */
#include <sys/mman.h>
#include <fcntl.h>           /* For O_* constants */
#include <semaphore.h>
#include <pthread.h>

namespace MICO {

/**
 *   Signals a problem with the execution of a SharedMemory call.
 */

class CSharedMemoryException: public std::exception
{
public:
/**
*   Construct a SharedMemoryException with a explanatory message.
*   @param message explanatory message
 *   @param bSysMsg true if system message (from strerror(errno))
*   should be postfixed to the user provided message
*/
CSharedMemoryException(const std::string &message, bool bSysMsg = false)   throw();


/** Destructor.
 * Virtual to allow for subclassing.
 */
virtual ~CSharedMemoryException() throw ();

/** Returns a pointer to the (constant) error description.
 *  @return A pointer to a \c const \c char*. The underlying memory
 *          is in posession of the \c Exception object. Callers \a must
 *          not attempt to free the memory.
 */
virtual const char* what() const throw (){  return m_sMsg.c_str(); }

protected:
/** Error message.
 */
std::string m_sMsg;
};

class CSharedMemory
{
public:
enum
{
C_READ_ONLY  = O_RDONLY,
C_READ_WRITE = O_RDWR,
} CREATE_MODE;

enum
{
  A_READ  = PROT_READ,
  A_WRITE = PROT_WRITE,
} ATTACH_MODE;

static std::string sLockSemaphoreName;
public:
CSharedMemory(const std::string& sName );
~CSharedMemory();

bool openSem(std::string sem);
bool Create(size_t nSize, int mode = C_READ_WRITE);
bool Attach(int mode = A_READ | A_WRITE);
bool Detach();
bool Lock();
bool UnLock();
int GetID() { return m_iD; }
void* GetData() { return m_Ptr; };
const void* GetData() const { return m_Ptr; }
private:
void Clear();
private:
std::string m_sName;
int m_iD;
sem_t* m_SemiD;
size_t m_nSize;
void* m_Ptr;

};

}

#endif // __mico_transport_sharedMemory_h_

Orb.cc class

void sharedMemory(string address, string sem, int length){
try{
MICO::CSharedMemory shmMemory(address);
shmMemory.Create(length);
shmMemory.Attach();
} catch(std::exception& e){
cout << "Exception:" <<e.what();
}

}

Source for Attach Method

bool
MICO::CSharedMemory::Attach( int mode /*= A_READ | A_WRITE*/ )
{
/* requesting the shared segment    --  mmap() */
m_Ptr = mmap(NULL, m_nSize, PROT_READ | PROT_WRITE, MAP_SHARED, m_iD, 0);
if (m_Ptr == NULL)
{
cout << "Error in attach";
throw CSharedMemoryException("Exception in attaching the shared memory  region");
}
return true;
}
tuergeist
  • 9,171
  • 3
  • 37
  • 58
Travis M
  • 58
  • 1
  • 1
  • 5
  • Where is the source for Attach()? Maybe the issue is with the mmap call. – Matthew Fisher Aug 05 '16 at 18:38
  • 1
    My crystal ball says you're making a temporary copy somewhere, and the destructor for that temporary is freeing the shared memory context. Follow the Rule of [Zero/Three/Four/Five](http://stackoverflow.com/q/4782757/103167). – Ben Voigt Aug 05 '16 at 18:41
  • Put debug logging in the destructor. – Ben Voigt Aug 05 '16 at 18:47
  • I've added the attach method to the post. Regarding the destructor for the temporary copy, how could I stop that from happening? I'm quite new with C++, but it was what this project was written in and I'm still figuring it all out. Thanks. – Travis M Aug 05 '16 at 18:48
  • Removing the call to the attach function still results in the same problem. – Travis M Aug 05 '16 at 19:08
  • I hacked a version of this code locally. It works fine. As @BenVoigt mentioned, put some debug output in the dtor or other spots where shm_unlink would be called. If fact, just star the debugger and put a break point on shm_unlink, it should only be called by your code if at all. – Matthew Fisher Aug 05 '16 at 19:59
  • I've found the issue, after running through a debugger as recommended it turns out, as stated, the destructor was being called. Thanks for the help. – Travis M Aug 05 '16 at 23:42

0 Answers0