mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-06-20 13:44:12 +02:00
Fix thread-unsafe QStandardPaths calls in dataDir/configDir
QStandardPaths::writableLocation() is not thread-safe in Qt5. ElementsCollectionModel::reload() launches: QtConcurrent::map(m_items_list_to_setUp, setUpData) Each worker calls FileElementCollectionItem::setUpData() → collectionPath() → isCollectionRoot() → QETApp::userMacrosDir() → QETApp::dataDir() → QStandardPaths::writableLocation() ← SIGSEGV (null deref) The crash was confirmed by Valgrind (address 0x0, inside libQt5Core's writableLocation internals). Fix: replace the bare QStandardPaths calls in dataDir() and configDir() with a C++11 static-local lambda. The compiler guarantees the lambda body runs exactly once across all threads (magic statics, ISO C++11 §6.7). After the first (main-thread) call the result is returned lock-free. Relates-to: #492 (same QtConcurrent lifetime pattern fixed in QETProject::writeBackup by PR #512).
This commit is contained in:
+16
-10
@@ -887,11 +887,14 @@ QString QETApp::configDir()
|
||||
#ifdef QET_ALLOW_OVERRIDE_CD_OPTION
|
||||
if (config_dir != QString()) return(config_dir);
|
||||
#endif
|
||||
QString configdir = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
|
||||
while (configdir.endsWith('/')) {
|
||||
configdir.remove(configdir.length()-1, 1);
|
||||
}
|
||||
return configdir;
|
||||
// C++11 static-local init runs exactly once across all threads — safe to
|
||||
// call from QtConcurrent background threads (QStandardPaths is not).
|
||||
static const QString cached = []() {
|
||||
QString d = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
|
||||
while (d.endsWith('/')) d.chop(1);
|
||||
return d;
|
||||
}();
|
||||
return cached;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -911,11 +914,14 @@ QString QETApp::dataDir()
|
||||
#ifdef QET_ALLOW_OVERRIDE_DD_OPTION
|
||||
if (data_dir != QString()) return(data_dir);
|
||||
#endif
|
||||
QString datadir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
while (datadir.endsWith('/')) {
|
||||
datadir.remove(datadir.length()-1, 1);
|
||||
}
|
||||
return datadir;
|
||||
// C++11 static-local init runs exactly once across all threads — safe to
|
||||
// call from QtConcurrent background threads (QStandardPaths is not).
|
||||
static const QString cached = []() {
|
||||
QString d = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
while (d.endsWith('/')) d.chop(1);
|
||||
return d;
|
||||
}();
|
||||
return cached;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user