I'm attempting to use boost's shared memory functionality to put a vector into shared memory, as discussed by this boost article.
It mostly all works, except sometimes, when I start up and the shared memory segment is already there, managed_shared_memory::find will hang.
The debugger shows it stuck on some interprocess mutex in the bowels of boost::interprocess.
I've checked and I have no other process that would be running that hangs on to this shared memory.
If follow my code, the test starts and if it discovers the segment already existing, it calls destroyMyShm(). destroyMyShm() opens up the segment and tries to call managed_shared_memory::find() on the vector that should be inside that segment. This find hangs.
Note if I just call shared_memory_object::remove() everything is ok. I don't know if this will cause a leak though because the vector won't be properly destroyed.
Is there anything I can do about this? Possibly a bug in boost?
Is it safe to just call shared_memory_object::remove() and forget about managed_shared_memory::destroy() ?
#include <gtest/gtest.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
typedef boost::interprocess::allocator<std::string, boost::interprocess::managed_shared_memory::segment_manager> ShmemAllocator;
typedef boost::interprocess::vector<std::string, ShmemAllocator> MyVector;
static const char *kSharedMemorySegmentName("myseg");
static const char *kSharedMemoryVectorName("myvec");
bool isMyShmCreated();
void destroyMyShm();
void initMyShm(size_t);
//pardon my google-test method here...
TEST(MyTest, SharedMemoryTest) {
using namespace boost::interprocess;
if (isMyShmCreated())
{
destroyMyShm(); //hangs in here (see below)
}
EXPECT_FALSE(isMyShmCreated());
initMyShm(1000000);
EXPECT_TRUE(isMyShmCreated());
managed_shared_memory segment(open_only, kSharedMemorySegmentName);
MyVector *vec = segment.find<MyVector>(kSharedMemoryVectorName).first;
EXPECT_TRUE(vec != 0);
vec->push_back(std::string("item 1"));
vec->push_back(std::string("item 2"));
destroyMyShm();
}
void initMyShm(size_t size) {
using namespace boost::interprocess;
if (isMyShmCreated()) {
log("already created");
}
managed_shared_memory segment(open_or_create, kSharedMemorySegmentName, size);
MyVector *vec = segment.find<MyVector>(kSharedMemoryVectorName).first;
if (!vec)
{
const ShmemAllocator alloc_inst (segment.get_segment_manager());
segment.construct<MyVector>(kSharedMemoryVectorName)(alloc_inst);
} else
{
vec->clear();
}
}
bool isMyShmCreated()
{
using namespace boost::interprocess;
try
{
managed_shared_memory segment(open_only, kSharedMemorySegmentName);
return segment.check_sanity();
} catch (const interprocess_exception &ex) {
std::cout << "managed_shared_memory ex: " << ex.what();
}
catch (const std::exception &ex) {
std::cout << "managed_shared_memory ex: " << ex.what();
}
catch (const std::string& ex)
{
std::cout << "managed_shared_memory ex: " << ex;
} catch (...)
{
std::cout << "managed_shared_memory ex: ?";
}
return false;
}
void destroyMyShm() {
using namespace boost::interprocess;
try
{
managed_shared_memory segment(open_only, kSharedMemorySegmentName);
// hangs on segment.find() below:
if (segment.find<MyVector>(kSharedMemoryVectorName).first)
segment.destroy<MyVector>(kSharedMemoryVectorName);
} catch (...) {}
try
{
shared_memory_object::remove(kSharedMemorySegmentName);
} catch (...) {}
}