0
votes

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 (...) {}
}
1

1 Answers

2
votes

shouldn't you be using basic_string<char, ShmemAllocator> instead of string? your vector is actually container of containers - all should use shared allocator I think. (you'd need two, one for the string - of chars - second for vector - of your special string)

EDIT: there is a link at the end of that boost page named 'Container of Containers'.... read it! (I was just guessing and that page proves I was correct.)

LINKS:
Boost: Creating vectors in shared memory
Boost: Containers of containers