Skip to content

is it ok to ignore this assertion? #76

@edwinchenloo

Description

@edwinchenloo

In my class header:

128 typedef moodycamel::BlockingConcurrentQueue < Underlying* > QueueUnderlyingPtr;
280 QueueUnderlyingPtr _qUnderlyingConflated;

I have this in my consumer thread:

30 , _qUnderlyingConflated( 10 * 1024 )
...
7790 typedef array < Underlying*, 32 > ArrayUnderlying;
7791 ArrayUnderlying arrUnderlying;
7792 moodycamel::ConsumerToken tokenConflated( _qUnderlyingConflated );
...
7871 const size_t uDequed = _qUnderlyingConflated.wait_dequeue_bulk_timed( tokenConflated
7872 , arrUnderlying.data()
7873 , arrUnderlying.size() // 32 entries
7874 , chrono::milliseconds( 100 ) );
7875
7876 if ( uDequed > 0 )
7877 {
7878 ...
7879

This in my producer threads ( i have a producer token that is a thread local variable):

1041 _qUnderlyingConflated.enqueue( *tokens._pConflated, &underlying );

i get this assertion checks in my consumer thread:

#0 0x00007f106e60df79 in __GI_raise (sig=sig@entry=0x6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
resultvar = 0x0
pid = 0xaa3
selftid = 0xbb0
#1 0x00007f106e611388 in __GI_abort () at abort.c:89
save_stage = 0x2
act = {__sigaction_handler = {sa_handler = 0x7f0cbae70000, sa_sigaction = 0x7f0cbae70000}, sa_mask = {__val = {0x7f10726f9000, 0x7f0cbfbf3060, 0x7f106d431819, 0x7f0cbae71900, 0x7f106d641fc0, 0x7f0cbae70000, 0x7f0cbae71900, 0x7f0cbfbf3080, 0x7f106d432207, 0x7f106e65ac30, 0x7f0cbae71900, 0x7f0cbfbf30a0, 0x7f106d43af76, 0x500000000, 0x7f0cbae71900, 0x7f0cbfbf30c0}}, sa_flags = 0x7174432d, sa_restorer = 0x7f106e9971c0 <IO_2_1_stderr>}
sigs = {__val = {0x20, 0x0 <repeats 15 times>}}
#2 0x00007f106e606e36 in __assert_fail_base (fmt=0x7f106e758718 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=assertion@entry=0x879b40 "!emptyFlags[i + j].load( std::memory_order_relaxed )", file=file@entry=0x879ac2 "ConcurrentQueue.h", line=line@entry=0x676, function=function@entry=0x87fc20 <bool moodycamel::ConcurrentQueue<Underlying*, moodycamel::ConcurrentQueueDefaultTraits>::Block::set_many_empty<(moodycamel::ConcurrentQueue<Underlying*, moodycamel::ConcurrentQueueDefaultTraits>::InnerQueueContext)1>(unsigned long, unsigned long)::PRETTY_FUNCTION> "bool moodycamel::ConcurrentQueue<T, Traits>::Block::set_many_empty(moodycamel::ConcurrentQueue<T, Traits>::index_t, moodycamel::ConcurrentQueue<T, Traits>::size_t) [with moodycamel::ConcurrentQueue<T,"...) at assert.c:92
str = 0x7f0cbae71900 ""
total = 0x1000
#3 0x00007f106e606ee2 in __GI___assert_fail (assertion=0x879b40 "!emptyFlags[i + j].load( std::memory_order_relaxed )", file=0x879ac2 "ConcurrentQueue.h", line=0x676, function=0x87fc20 <bool moodycamel::ConcurrentQueue<Underlying*, moodycamel::ConcurrentQueueDefaultTraits>::Block::set_many_empty<(moodycamel::ConcurrentQueue<Underlying*, moodycamel::ConcurrentQueueDefaultTraits>::InnerQueueContext)1>(unsigned long, unsigned long)::PRETTY_FUNCTION> "bool moodycamel::ConcurrentQueue<T, Traits>::Block::set_many_empty(moodycamel::ConcurrentQueue<T, Traits>::index_t, moodycamel::ConcurrentQueue<T, Traits>::size_t) [with moodycamel::ConcurrentQueue<T,"...) at assert.c:101
No locals.
#4 0x00000000004fad8d in moodycamel::ConcurrentQueue<Underlying*, moodycamel::ConcurrentQueueDefaultTraits>::Block::set_many_empty<(moodycamel::ConcurrentQueue<Underlying*, moodycamel::ConcurrentQueueDefaultTraits>::InnerQueueContext)1> (this=0x7f1067f32fa0, i=0x0, count=0x1) at ConcurrentQueue.h:1654
j = 0x0
PRETTY_FUNCTION = "bool moodycamel::ConcurrentQueue<T, Traits>::Block::set_many_empty(moodycamel::ConcurrentQueue<T, Traits>::index_t, moodycamel::ConcurrentQueue<T, Traits>::size_t) [with moodycamel::ConcurrentQueue<T,"...
#5 0x00000000004f61ab in moodycamel::ConcurrentQueue<Underlying*, moodycamel::ConcurrentQueueDefaultTraits>::ExplicitProducer::dequeue_bulk<Underlying**> (this=0x7f0ca4443ec0, itemFirst=@0x7f0cbfbf3398: 0x7f0cbfbf36e8, max=0x4) at ConcurrentQueue.h:2436
firstIndexInBlock = 0x229f
endIndex = 0x22a0
block = 0x7f1067f32fa0
firstIndex = 0x229f
indexIndex = 0x116
localBlockIndex = 0x7f10574da080
localBlockIndexHead = 0x117
headBase = 0x22a0
firstBlockBaseIndex = 0x2280
offset = 0x7ffffffffffffff
index = 0x22a0
myDequeueCount = 0x229f
actualCount = 0x4
PRETTY_FUNCTION = "moodycamel::ConcurrentQueue<T, Traits>::size_t moodycamel::ConcurrentQueue<T, Traits>::ExplicitProducer::dequeue_bulk(It&, moodycamel::ConcurrentQueue<T, Traits>::size_t) [with It = Underlying**; T = "...
tail = 0x22a9
overcommit = 0x0
desiredCount = 0x4
#6 0x00000000004f06eb in moodycamel::ConcurrentQueue<Underlying*, moodycamel::ConcurrentQueueDefaultTraits>::ProducerBase::dequeue_bulk<Underlying**> (this=0x7f0ca4443ec0, itemFirst=@0x7f0cbfbf3398: 0x7f0cbfbf36e8, max=0x4) at ConcurrentQueue.h:1788
No locals.
#7 0x00000000004e7953 in moodycamel::ConcurrentQueue<Underlying*, moodycamel::ConcurrentQueueDefaultTraits>::try_dequeue_bulk<Underlying**&> (this=0x7f1069d2e260, token=..., itemFirst=@0x7f0cbfbf3398: 0x7f0cbfbf36e8, max=0x4) at ConcurrentQueue.h:1287
dequeued = 0x0
count = 0x1c
tail = 0x7f0c97d3fec0
ptr = 0x7f0ca4443ec0
#8 0x00000000004de256 in moodycamel::BlockingConcurrentQueue<Underlying*, moodycamel::ConcurrentQueueDefaultTraits>::wait_dequeue_bulk_timed<Underlying**&> (this=0x7f1069d2e260, token=..., itemFirst=@0x7f0cbfbf3398: 0x7f0cbfbf36e8, max=0x20, timeout_usecs=0x186a0) at BlockingConcurrentQueue.h:930
count = 0x0
#9 0x00000000004d738e in moodycamel::BlockingConcurrentQueue<Underlying*, moodycamel::ConcurrentQueueDefaultTraits>::wait_dequeue_bulk_timed<Underlying**, long, std::ratio<1l, 1000l> > (this=0x7f1069d2e260, token=..., itemFirst=0x7f0cbfbf36e8, max=0x20, timeout=...) at BlockingConcurrentQueue.h:943
No locals.
#10 0x00000000004c8e33 in TradePublish::runUnderlyingConflatedFeed (this=0x7f1069d2d080, nCore=0x18) at TradePublish.cpp:7874
vFilter = {<std::_Vector_base<TradePublish::UnderlyingFilter, std::allocatorTradePublish::UnderlyingFilter >> = {_M_impl = {<std::allocatorTradePublish::UnderlyingFilter> = {<__gnu_cxx::new_allocatorTradePublish::UnderlyingFilter> = {}, }, _M_start = 0x0, _M_finish = 0x0, _M_end_of_storage = 0x0}}, }

Of special interest is the assert on frame #4. There is an array of atomics. The assert expected an entry to be false but it was true:

#4 0x00000000004fad8d in moodycamel::ConcurrentQueue<Underlying*, moodycamel::ConcurrentQueueDefaultTraits>::Block::set_many_empty<(moodycamel::ConcurrentQueue<Underlying*, moodycamel::ConcurrentQueueDefaultTraits>::InnerQueueContext)1> (this=0x7f1067f32fa0, i=0x0, count=0x1) at ConcurrentQueue.h:1654
1654 assert( !emptyFlags[i + j].load( std::memory_order_relaxed ) );
gdb$ list 1641,1666
1641
1642 // Sets multiple contiguous item statuses to 'empty' (assumes no wrapping and count > 0).
1643 // Returns true if the block is now empty (does not apply in explicit context).
1644 template < InnerQueueContext context >
1645 inline bool set_many_empty( index_t i, size_t count )
1646 {
1647 if ( context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD )
1648 {
1649 // Set flags
1650 std::atomic_thread_fence( std::memory_order_release );
1651 i = BLOCK_SIZE - 1 - static_cast < size_t >( i & static_cast < index_t >( BLOCK_SIZE - 1 ) ) - count + 1;
1652 for ( size_t j = 0; j != count; ++j )
1653 {
1654 assert( !emptyFlags[i + j].load( std::memory_order_relaxed ) );
1655 emptyFlags[i + j].store( true, std::memory_order_relaxed );
1656 }
1657 return false;
1658 }
1659 else
1660 {
1661 // Increment counter
1662 auto prevVal = elementsCompletelyDequeued.fetch_add( count, std::memory_order_release );
1663 assert( prevVal + count <= BLOCK_SIZE );
1664 return prevVal + count == BLOCK_SIZE;
1665 }
1666 }

gdb$ p i
$8 = 0x0
gdb$ p j
$9 = 0x0
gdb$ p count
$10 = 0x1
gdb$ p emptyFlags
$11 = {{std::atomic_bool = {_M_base = {M_i = 0x1}}, } <repeats 32 times>}
gdb$ p context
$12 = moodycamel::ConcurrentQueue<Underlying*, moodycamel::ConcurrentQueueDefaultTraits>::explicit_context
gdb$ p explicit_context
$13 = moodycamel::ConcurrentQueue<Underlying*, moodycamel::ConcurrentQueueDefaultTraits>::explicit_context
gdb$ p BLOCK_SIZE
$14 = 0x20
gdb$ p EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD
$15 = 0x20
gdb$ p this
$16 = (moodycamel::ConcurrentQueue<Underlying*, moodycamel::ConcurrentQueueDefaultTraits>::Block * const) 0x7f1067f32fa0
gdb$ p *this
gdb$ p *this
$17 = {
{
elements = "\000A\361\020\177\000\000\200 4a\020\177\000\000\000A\361\020\177\000\000\000\001\346\020\177\000\000\300\020\237h\020\177\000\000\000\201rh\020\177\000\000\300\020\237h\020\177\000\000\300\320Hh\020\177\000\000\200\240\020h\020\177\000\000\300P\212\020\177\000\000\000\201rh\020\177\000\000\300\020\237h\020\177\000\000\300PWa\020\177\000\000\000\001\346`\020\177\000\000\000\201rh\020\177\000\000\300\220wh\020\177\000\000@\360Da\020\177\000\000\200\340ch\020\177\000\000\200\240\020h\020\177\000\000@0\vh\020\177\000\000\300P\256
\020\177\000\000\300\020Da\020\177\000\000\000A\205h\020\177\000\000\300\320Hh\020\177\000\000\300\020\237h\020\177\000\000"...,
dummy = {
__max_align_ll = 0x7f1060f14100,
__max_align_ld =
}
},
next = 0x7f1067f33630,
elementsCompletelyDequeued = {
<std::__atomic_base> = {
_M_i = 0x0
}, },
emptyFlags = {{
std::atomic_bool = {
_M_base = {
_M_i = 0x1
}
}, } <repeats 32 times>},
freeListRefs = {
<std::__atomic_base> = {
_M_i = 0x0
}, },
freeListNext = {
_M_b = {
_M_p = 0x0
}
},
shouldBeOnFreeList = {
std::atomic_bool = {
_M_base = {
_M_i = 0x0
}
}, },
dynamicallyAllocated = 0x0
}

I'm thinking to ignore the assert but maybe that first if statement in ConcurrentQueue:1647 needs to be modified.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions