Boost logo

Boost Users :

Subject: Re: [Boost-users] boost::interprocess segfault when calling pop on deque
From: OvermindDL1 (overminddl1_at_[hidden])
Date: 2010-07-29 21:16:26


On Tue, Jul 27, 2010 at 2:45 PM, Matthew Stump <mstump_at_[hidden]> wrote:
> I built a datastrucuture which I called BufferedQueue.  It's
> essentially a double buffered queue but instead of two buffers I allow
> a user specified number of buffers.  Each buffer is a struct which
> contains the managed_mapped_file for the particular buffer and a
> pointer to a boost::interprocess::deque.  Each mapped file contains
> only 1 deque and the deque is used to store items pushed onto the
> queue by the user.  I automatically handle rotation between the
> various buffers when the user calls push or pop.
>
> Specific problem:
> All of my functional unit tests pass without issue and I have 100%
> test coverage.  When I run the multi-threaded unit tests I encounter a
> segfault, but not immediately.  I have some tests which will spawn one
> thread which instantiates the datastrucutre and will push 100K items
> onto the queue (this will span multiple buffers).  I spawn a second
> thread which also instantiates the datastrucutre and begin to pop
> items off of the queue.  After about 40K items have been poped off of
> the queue I get a segfault when calling
> boost::interprocess::deque::pop_front().  It's always on the same
> line, and occurs when the segment manager is doing it's sanity checks
> while de-allocating the memory.  Sometimes this occurs when it's the
> last item in the deque which is being poped, sometimes it's not; there
> is no detectable pattern.  For my test I'm also using ints so I'm not
> pushing something onto the datastrucutre that isn't compatible with
> boost::interprocess.
>
> Any helpful ideas as to what may be the cause of my problem would be greatly appreciated.
>
> // Type declarations for the deque
> typedef boost::interprocess::managed_mapped_file                    ManagedFile;
> typedef ManagedFile::segment_manager                                SegmentManager;
> typedef typename boost::interprocess::allocator<T, SegmentManager>  TypeAllocator;
> typedef typename boost::interprocess::list<T, TypeAllocator>        MMContainer;
>
> // instantiation of the deque
> queue = file.find_or_construct<MMContainer>(getBufferName(name, buffNum).c_str())(TypeAllocator(file.get_segment_manager()));
>
> // my pop method
> template<class T>
> void
> BufferedQueue<T>::pop()
> {
>    checkBufferCount();
>
>    {
>        boost::interprocess::sharable_lock<Mutex> master_lock(*m_masterMutex);
>        boost::interprocess::scoped_lock<typename Buffer<T>::Mutex> lock(*getReadBuffer().mutex);
>
>        assert(getReadBuffer().queue);
>        if (!isBufferEmpty<T>(getReadBuffer()))
>        {
>            assert(!getReadBuffer().queue->empty());
>            getReadBuffer().queue->pop_front();
>            return;
>        }
>    }
>
>    rotate_reader();
>    boost::interprocess::sharable_lock<Mutex> master_lock(*m_masterMutex);
>    boost::interprocess::scoped_lock<typename Buffer<T>::Mutex> lock(*getReadBuffer().mutex);
>    if (isBufferEmpty<T>(getReadBuffer()))
>        throw Exception("called pop() on an empty buffer");
>
>    assert(!getReadBuffer().queue->empty());
>    getReadBuffer().queue->pop_front();
> }
>
> /libs2/external/boost/boost/interprocess/mem_algo/rbtree_best_fit.hpp:1244: void boost::interprocess::rbtree_best_fit<MutexFamily, VoidMutex, MemAlignment>::priv_deallocate(void*) [with MutexFamily = boost::interprocess::mutex_family, VoidPointer = boost::interprocess::offset_ptr<void>, unsigned int MemAlignment = 0u]: Assertion `priv_is_allocated_block(block)' failed.
>
> #0  0x0094a410 in __kernel_vsyscall ()
> #1  0x02850df0 in raise () from /lib/libc.so.6
> #2  0x02852701 in abort () from /lib/libc.so.6
> #3  0x0284a26b in __assert_fail () from /lib/libc.so.6
> #4  0x0806ca9f in boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0u>::priv_deallocate (this=0xb5fcd004, addr=0xb5fcd0b8)
>    at /libs2/external/boost/boost/interprocess/mem_algo/rbtree_best_fit.hpp:1244
> #5  0x0807b00b in boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0u>::deallocate (this=0xb5fcd004, addr=0xb5fcd0b8)
>    at /libs2/external/boost/boost/interprocess/mem_algo/rbtree_best_fit.hpp:1233
> #6  0x0807b05f in boost::interprocess::segment_manager_base<boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0u> >::deallocate
>    (this=0xb5fcd004, addr=0xb5fcd0b8) at /libs2/external/boost/boost/interprocess/segment_manager.hpp:217
> #7  0x0807b5fe in boost::interprocess::allocator<boost::container::containers_detail::list_node<int, boost::interprocess::offset_ptr<void> >, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0u>, boost::interprocess::iset_index> >::deallocate (this=0xb5fcd0b0, ptr=...)
>    at /libs2/external/boost/boost/interprocess/allocators/allocator.hpp:152
> #8  0x0807b61c in boost::interprocess::allocator<boost::container::containers_detail::list_node<int, boost::interprocess::offset_ptr<void> >, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0u>, boost::interprocess::iset_index> >::deallocate_one (this=0xb5fcd0b0, p=...)
>    at /libs2/external/boost/boost/interprocess/allocators/allocator.hpp:234
> #9  0x0807b693 in boost::container::containers_detail::allocator_destroyer<boost::interprocess::allocator<boost::container::containers_detail::list_node<int, boost::interprocess::offset_ptr<void> >, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0u>, boost::interprocess::iset_index> > >::priv_deallocate (this=0x43511dc, p=...) at /libs2/external/boost/boost/interprocess/containers/container/detail/destroyers.hpp:133
> #10 0x0807b6ca in boost::container::containers_detail::allocator_destroyer<boost::interprocess::allocator<boost::container::containers_detail::list_node<int, boost::interprocess::offset_ptr<void> >, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0u>, boost::interprocess::iset_index> > >::operator() (this=0x43511dc, p=...) at /libs2/external/boost/boost/interprocess/containers/container/detail/destroyers.hpp:143
> #11 0x0807b786 in boost::intrusive::list_impl<boost::intrusive::listopt<boost::intrusive::detail::base_hook_traits<boost::container::containers_detail::list_node<int, boost::interprocess::offset_ptr<void> >, boost::intrusive::list_node_traits<boost::interprocess::offset_ptr<void> >, normal_link, boost::intrusive::default_tag, 1>, unsigned int, true> >::erase_and_dispose<boost::container::containers_detail::allocator_destroyer<boost::interprocess::allocator<boost::container::containers_detail::list_node<int, boost::interprocess::offset_ptr<void> >, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0u>, boost::interprocess::iset_index> > > > (
>    this=0xb5fcd0b4, i=..., disposer=...) at /libs2/external/boost/boost/intrusive/list.hpp:649
> #12 0x0807b7ce in boost::intrusive::list_impl<boost::intrusive::listopt<boost::intrusive::detail::base_hook_traits<boost::container::containers_detail::list_node<int, boost::interprocess::offset_ptr<void> >, boost::intrusive::list_node_traits<boost::interprocess::offset_ptr<void> >, normal_link, boost::intrusive::default_tag, 1>, unsigned int, true> >::erase_and_dispose<boost::container::containers_detail::allocator_destroyer<boost::interprocess::allocator<boost::container::containers_detail::list_node<int, boost::interprocess::offset_ptr<void> >, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0u>, boost::interprocess::iset_index> > > > (
>    this=0xb5fcd0b4, i=..., disposer=...) at /libs2/external/boost/boost/intrusive/list.hpp:656
> #13 0x0807b839 in boost::container::list<int, boost::interprocess::allocator<int, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0u>, boost::interprocess::iset_index> > >::erase (this=0xb5fcd0b0, p=...)
>    at /libs2/external/boost/boost/interprocess/containers/container/list.hpp:930
> #14 0x0807b881 in boost::container::list<int, boost::interprocess::allocator<int, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0u>, boost::interprocess::iset_index> > >::pop_front (this=0xb5fcd0b0)
>    at /libs2/external/boost/boost/interprocess/containers/container/list.hpp:623
> #15 0x0808a2e2 in Ovid::BufferedQueue<int>::pop (this=0x43512f0) at /ovid/server/shared/ovidserver-bufferedqueue.cpp:287
> #16 0x080557fb in reader_multithread_two_writer_single_reader_throughput () at test-ovidserver-bufferedqueue.cpp:389
> #17 0x07653832 in start_thread () from /lib/libpthread.so.0
> #18 0x028f9e0e in clone () from /lib/libc.so.6

It is best if you can supply a completely self-contained (using boost
of course) example that demonstrates the issue.


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net