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

Reply via email to