hey guys,
so after playing with the bug last night, here's the recap:
One place that was causing a side effect of the issue was in
midiledcontrol.cpp, it was using a control object without seeing if
ControlObject::getControl returned null. In this case, it was returning
null, but for a control like ("[Channel1]", "play"), something that
definitely exists. We made it test for null, but the root cause was
still unknown.
We scratched our heads a bit, and looked at getControl -- it uses a
Q3PtrList. After printlining the entry and exit to getControl, we found
this: http://pastebin.com/m308ae53f
Basically, the problem goes hand in hand with a double 'ENTER'. It turns
out the line:
for(c=m_sqList.begin(); c; c=m_sqList.next())
Implies that the Q3PtrList keeps track of the iterator internally, which
means it's definitely not safe for two threads to iterate at the same
time. The reason that it's missing something that exists like 'play' is
that if both threads hit their m_sqList.next() call at the same time,
then whichever 'current' node won the race then gets incremented twice.
It's also is not supposed to be iterated while appended or removed from,
so the ControlObject creation and destruction needs locking too.
So we probably need a lock at least on append and remove from this list.
If we upgrade from Q3PtrList to QList, we can use QList::const_iterator
which returns an iterator object that will not be screwed up by other
threads iterating the object. The docs say an iterator becomes undefined
if you append or remove while using it though, so technically we could
have an issue if we append to the list while iterating. -- sketchy
Adding a lock to getControl, append, and remove on my branch caused it
to go away. So that's good. I'm also curious about what other subtle
bugs this might be linked to. We've only encountered one of the three
races that exist here. The other two are iterate / append and
iterate/destroy (and I guess, append/destroy, and destroy/destroy). It's
definitely a longshot, but some of those 'not exiting cleanly' style
bugs might be caused by something like a two controlobjects being
destroyed at once so their remove calls to m_sqList conflict and trash
the datastructure. shrug.. it's nice to dream right :)
Moving to QList seems good regardless (because const_iterator is faster,
it's newer, get rid of QT3 stuff, etc) So the question remaining is
whether or not to lock inside of getControl...
RJ
-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08
_______________________________________________
Mixxx-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mixxx-devel