Crash when running an XQuery via QtConcurrent::run
-
Hi all,
I have a couple of XQueries to read XML music libraries in two different formats. Both the routines are static, and they take roughly the same form:
@QList<QUrl> ExternalPlaylist::readTraktorLibraryPlaylist(const QString& playlistName, const Preferences& prefs){
QMutexLocker locker(&externalPlaylistMutex);
QStringList resultStrings;
QList<QUrl> results;QFile xmlFile(prefs.getTraktorLibraryPath());
if (!xmlFile.open(QIODevice::ReadOnly))
return results;QXmlQuery xmlQuery;
xmlQuery.bindVariable("inputDocument", &xmlFile);
xmlQuery.bindVariable("playlistName", QVariant(playlistName));QString xPath;
xPath += "doc($inputDocument)//NODE[@TYPE='PLAYLIST' and @NAME=($playlistName)]";
xPath += "/PLAYLIST[@TYPE='LIST']/ENTRY/PRIMARYKEY/@KEY/string(.)";xmlQuery.setQuery(xPath);
if(xmlQuery.evaluateTo(&resultStrings))
for(int i=0; i<(signed)resultStrings.size(); i++)
results.push_back(fixTraktorAddressing(resultStrings[i]));xmlFile.close();
return results;
}@That function works absolutely fine, whether it's run in the GUI thread or via QtConcurrent::run. Its sibling is basically the same except for the XQuery string:
@ xPath += "let $d := doc($inputDocument)/plist/dict ";
xPath += "for $track in $d/array[preceding-sibling::key[1]='Playlists']";
xPath += "/dict[child::string[preceding-sibling::key[1]='Name'][1]=($playlistName)]";
xPath += "/array/dict/integer[preceding-sibling::key[1]='Track ID'] ";
xPath += "return $d/dict[preceding-sibling::key[1]='Tracks']";
xPath += "/dict[preceding-sibling::key[1]=$track]";
xPath += "/string[preceding-sibling::key[1]='Location']/string(text())";@... only this time, it works fine in the GUI thread but when run via QtConcurrent::run, it crashes while attempting xmlQuery.evaluateTo(&resultStrings), with EXC_BAD_ACCESS (SIGBUS). Now, obviously, this query is a lot more complex (it's for parsing the iTunes library) and is much less efficient, running in something like quadratic time rather than linear. But it's obviously functional, or it wouldn't run in the GUI thread. This makes me think there must be something wrong with the surrounding function; something I'm missing with regard to QtConcurrent compatibility. Does anyone have any ideas?
I've pasted the crash log below; the last row is repeated literally hundreds of times in the error report but I've snipped it here.
@Thread 4 Crashed:
0 libsystem_c.dylib 0x00007fff930a3c19 szone_malloc_should_clear + 102
1 libsystem_c.dylib 0x00007fff930d93c8 malloc_zone_malloc + 77
2 libsystem_c.dylib 0x00007fff930da1a4 malloc + 44
3 libstdc++.6.dylib 0x00007fff887c168e operator new(unsigned long) + 94
4 QtXmlPatterns 0x00000001010778d4 QPatternist::AccelTree::iterate(QXmlNodeModelIndex const&, QXmlNodeModelIndex::Axis) const + 2704
5 QtXmlPatterns 0x00000001010cb4ab QPatternist::AxisStep::evaluateSequence(QExplicitlySharedDataPointerQPatternist::DynamicContext const&) const + 265
6 QtXmlPatterns 0x00000001010e2352 QPatternist::FirstItemPredicate::evaluateSingleton(QExplicitlySharedDataPointerQPatternist::DynamicContext const&) const + 26
7 QtXmlPatterns 0x000000010115004c QPatternist::Atomizer::evaluateSingleton(QExplicitlySharedDataPointerQPatternist::DynamicContext const&) const + 26
8 QtXmlPatterns 0x0000000101100773 QPatternist::ValueComparison::evaluateSingleton(QExplicitlySharedDataPointerQPatternist::DynamicContext const&) const + 39
9 QtXmlPatterns 0x00000001010d920a QPatternist::Expression::evaluateSequence(QExplicitlySharedDataPointerQPatternist::DynamicContext const&) const + 22
10 QtXmlPatterns 0x00000001010e8887 QPatternist::GenericPredicate::mapToItem(QPatternist::Item const&, QExplicitlySharedDataPointerQPatternist::DynamicContext const&) const + 53
11 QtXmlPatterns 0x00000001010e83f8 QPatternist::ItemMappingIterator<QPatternist::Item, QPatternist::Item, QExplicitlySharedDataPointer<QPatternist::GenericPredicate const>, QExplicitlySharedDataPointerQPatternist::DynamicContext >::next() + 148
12 QtXmlPatterns 0x00000001010e8489 QPatternist::ItemMappingIterator<QPatternist::Item, QPatternist::Item, QExplicitlySharedDataPointer<QPatternist::GenericPredicate const>, QExplicitlySharedDataPointerQPatternist::DynamicContext >::next() + 293
13 QtXmlPatterns 0x00000001010e8489 QPatternist::ItemMappingIterator<QPatternist::Item, QPatternist::Item, QExplicitlySharedDataPointer<QPatternist::GenericPredicate const>, QExplicitlySharedDataPointerQPatternist::DynamicContext >::next() + 293
14 QtXmlPatterns 0x00000001010e8489 QPatternist::ItemMappingIterator<QPatternist::Item, QPatternist::Item, QExplicitlySharedDataPointer<QPatternist::GenericPredicate const>, QExplicitlySharedDataPointerQPatternist::DynamicContext >::next() + 293@Any help appreciated. Thanks.
-
Truly, this is a pain. I've just tested this code on Qt 4.8.0 (having been using 4.7.4 thus far) and the problem is still present.
I also tried a variant running the XQuery in another QThread but it was even less stable; any XQuery at all was segfaulting.
Anyone have any ideas? Or does anyone have any examples of a recursive QXmlQuery working outside the GUI thread?
Cheers
-
Couldn't recreate this on Windows so perhaps it's Mac only. Will try and test it on a pre-Lion Mac to narrow it down further.
(Sorry, I know I seem to be basically using this thread as a notepad now, but hopefully I'll be able to cobble together enough info for a bug report at least).