Boost logo

Geometry :

Subject: [geometry] Crash in rtree after growing shared memory, VS2012 x64, Boost 1.55
From: Tim Finer (tim.finer_at_[hidden])
Date: 2014-07-25 13:49:02


Hello,

I really want to use a persistent rtree backed by shared memory (or a
memory mapped file). I don't know in advance how large the data. I
experimented with resizing a boost::vector backed by a shared memory
allocator and applied what I found there to the example at
http://www.boost.org/doc/libs/1_55_0/libs/geometry/doc/html/geometry/spatial_indexes/rtree_examples/index_stored_in_shared_memory_using_boost_interprocess.html.

What I did was wrap an insertion function that catches a bad_alloc,
closes the shared memory segment, grows the shared memory, then resets
the pointer to the rtree. I've verified that this technique works fine
for boost::vector, but not for the rtree, because it appears that there
are some other structures internally that are possibly noting the (old)
capacity of the shared memory?

I also noted in a previous thread a similar problem, and applied the fix
on github, but that didn't help
(http://boost-geometry.203548.n3.nabble.com/rtree-crash-when-used-with-inter-process-td4026037.html).

    namespace bg = boost::geometry;
    namespace bgm = boost::geometry::model;
    namespace bgi = boost::geometry::index;
    namespace bi = boost::interprocess;

    typedef bgm::point<double, 3, bg::cs::cartesian> bgPoint3;
    typedef std::pair<bgPoint3, std::uint64_t> bgValue;
    typedef bgm::box<bgPoint3> bgBox3;

    typedef bgi::linear<16> Partitioner;
    typedef bgi::indexable<bgValue> Indexer;
    typedef bgi::equal_to<bgValue> Comparator;
    typedef bi::allocator<bgValue,
bi::managed_shared_memory::segment_manager> Allocator;
    typedef bgi::rtree<bgValue, Partitioner, Indexer, Comparator,
Allocator > bgMemRTree;
    typedef std::unique_ptr<bi::managed_shared_memory> MemPtr;

    inline void ResizingInsert(MemPtr& mem, bgMemRTree*& rtree, const
bgPoint3& pt, std::uint64_t i)
    {
       try
       {
          rtree->insert(std::make_pair(pt, i));
       }
       catch(bi::bad_alloc&)
       {
          auto newSize = static_cast<size_t>(mem->get_size() * 0.5);

          // Close
          mem.reset();
          bi::managed_shared_memory::grow("RTree-Test", newSize);
          mem.reset(new bi::managed_shared_memory(bi::open_only,
"RTree-Test"));
          rtree = mem->find<bgMemRTree>("rtree").first;

          // Try again, let bad_alloc out if this fails a second time.
          rtree->insert(std::make_pair(pt, i));
       }
    }

    MemPtr mem(new bi::managed_shared_memory(bi::create_only,
"RTree-Test", 1024 * 64));

    for ( std::uint64_t i = 0 ; i < 50000; ++i )
       ResizingInsert( mem, rtree, bgPoint3(rndDbl(prng), rndDbl(prng),
rndDbl(prng)), i);

    Dies down in
Boost_1.55.0\Boost\boost\geometry\index\detail\varray.hpp:74
    BOOST_GEOMETRY_INDEX_ASSERT(s <= v.capacity(), "size too big");

I'm not married to the way I'm doing this, and welcome any suggestions
or workarounds. My other thought is copying the entire tree into a new
(larger) shared memory segment, but I'm sure that'll be a huge
performance hit.

Thanks in Advance,
Tim


Geometry list run by mateusz at loskot.net