I'm running into issues with using interprocess containers have other containers added to them during runtime. A very high level description is I have a set of data structures in shared memory that can be accessed and modified by more than one process. I'm creating the data structures in the first process and storing the name of the segment within the data structure. Methods that modify the data by adding another container first lookup the segment using its name, build the new container, and then insert it into the existing container. In the example I'm providing below, I have a map of lists. For some reason, when I add a new list, if I open the segment by name, and allocate the list using the segment manager returned via the lookup, the list isn't initialized correctly and accessing the list (via printData here) results in a segfault. However, if I bypass the segment lookup and just cache the raw pointer to the segment, it works. It's probably easiest just to look at the code below. In addMessage, you can see how I'm trying to initialize the list in a manner that will work across multiple processes. This breaks. Commented out directly below it is a hack that will work. I can't see any reason why one works and the other doesn't. The "managed_shared_memory" object returned from the lookup appears to be valid and exactly the same as the pointer I'm caching with the data structure in this example.
I am currently using 1.49 final, but I've observed similar behavior in other 1.4x releases.
=================================BEGIN CODE====================================================
#include
#include <cstddef>
#include <string>
#include <functional>
#include <iostream>
#include <utility>
using std::cerr;
using std::endl;
using std::pair;
#include
#include
#include
#include
#include
#include
#include
using namespace boost::interprocess;
class SharedMemoryDeleter {
public:
SharedMemoryDeleter(const std::string& name) : mName(name) {
shared_memory_object::remove(mName.c_str());
}
~SharedMemoryDeleter() {
shared_memory_object::remove(mName.c_str());
}
protected:
std::string mName;
};
class TestStore {
public:
struct TestData {
uint16_t commandStatus;
size_t wordCount;
uint16_t data[32];
};
///Allocates characters in shared memory
typedef allocator CharAllocator;
///String in shared memory
typedef basic_string SharedMemoryString;
///Allocates list in shared memory
typedef allocator ListAllocator;
///List of TestData items in shared memory
typedef list SharedMemoryList;
///Key/Value pair for the map (SA, Data List)
typedef pair data_map_value_t;
///Allocates maps in shared memory
typedef allocator MapAllocator;
///Maps lists to SAs in shared memory
typedef map SharedMemoryMap;
TestStore(managed_shared_memory& segment, const std::string& name) :
mSegment(&segment),
mSegmentName(name.c_str(),
CharAllocator(mSegment->get_segment_manager())),
mData(std::less<unsigned>(), MapAllocator(mSegment->get_segment_manager())){
}
///////////////////////////////////////////////////////////////////////////
/// Destructor
///////////////////////////////////////////////////////////////////////////
virtual ~TestStore() {
}
void printData() {
TestStore::SharedMemoryMap::iterator it = mData.begin();
while(it != mData.end()) {
TestStore::SharedMemoryList::iterator lIt = it->second.begin();
cerr << "SA: " << it->first << endl;
cerr << it->second.size() << endl;
while (lIt != it->second.end()) {
cerr << "\titerating..." << endl;
cerr << "wc: " << lIt->wordCount << endl;
cerr << "cs: " << lIt->commandStatus << endl;
cerr << "\t" << lIt->commandStatus << ", WC: "
<< lIt->wordCount << endl;
++lIt;
}
++it;
}
cerr << endl;
}
bool addMessage(unsigned key, const TestData& data) {
TestStore::SharedMemoryMap::iterator it = mData.find(key);
cerr << "Adding word count " << data.wordCount << endl;
if(it != mData.end()) {
it->second.push_back(data);
}
else {
cerr << "Looking for " << mSegmentName.c_str() << endl;
managed_shared_memory m(open_only, mSegmentName.c_str());
cerr << "found it" << endl;
cerr << m.check_sanity() << " - " << m.get_free_memory() << "/" << m.get_size() << endl;
cerr << mSegment->check_sanity() << " * " << mSegment->get_free_memory() << "/" << mSegment->get_size() << endl;
///!!!!!!!!!!!!!!!BROKE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
TestStore::SharedMemoryList sList(TestStore::ListAllocator(
m.get_segment_manager()));
//==========This Works (obviously only for current process)===========
// TestStore::SharedMemoryList sList(TestStore::ListAllocator(
// mSegment->get_segment_manager()));
sList.push_back(data);
cerr << "pushed" << endl;
cerr << sList.front().wordCount << endl;
mData.insert(TestStore::SharedMemoryMap::value_type(key, sList));
cerr << "added list" << endl;
}
cerr << "====================Data post add===================" << endl;
printData();
return true;
}
private:
///Segment housing this class. Only valid in the constructing process
managed_shared_memory* mSegment;
///Name of the segment
SharedMemoryString mSegmentName;
SharedMemoryMap mData;
};
int main() {
std::string name = "MemHere";
int num_bytes = 645360;
SharedMemoryDeleter deleter(name);
managed_shared_memory shm(open_or_create, name.c_str(), num_bytes);
TestStore store(shm, name);
TestStore::TestData data;
data.commandStatus = 10;
data.wordCount = 14;
store.addMessage(3, data);
return 0;
}