From 2fc4a1b53042b69bdb745e2e69c861eecf945b3c Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 28 Sep 2021 12:52:15 +0200 Subject: gl: Try the local CacheLocation when the shared one fails We prefer the shared cache path, because there is no reason to give up benefitting from sharing the content between applications. If that path is not QFileInfo().isWritable(), we fall back to the local cache path. However, there are reportedly systems with security solutions such as AppArmor where the writable check passes and yet attempting to create a file still fails. Then there is no cache in effect, because nothing ever gets written out. Handle this better: if writing the file fails and we still use our first choice, the global cache location, fall back to the secondary choice (the app-local path) and try again. Fixes: QTBUG-96789 Change-Id: Ifea32e9af0cf85aa70f3069256ed3d6a7e2fbe90 Reviewed-by: Qt CI Bot Reviewed-by: Dalton Durst Reviewed-by: Andy Nichols (cherry picked from commit 46e6a9a759ae89f905107ccad191ca5ddf442e53) Reviewed-by: Qt Cherry-pick Bot --- src/gui/opengl/qopenglprogrambinarycache.cpp | 61 +++++++++++++++++++--------- 1 file changed, 42 insertions(+), 19 deletions(-) (limited to 'src/gui/opengl/qopenglprogrambinarycache.cpp') diff --git a/src/gui/opengl/qopenglprogrambinarycache.cpp b/src/gui/opengl/qopenglprogrambinarycache.cpp index 631c3d151b..8b0075bf26 100644 --- a/src/gui/opengl/qopenglprogrambinarycache.cpp +++ b/src/gui/opengl/qopenglprogrambinarycache.cpp @@ -119,20 +119,24 @@ QOpenGLProgramBinaryCache::QOpenGLProgramBinaryCache() { const QString subPath = QLatin1String("/qtshadercache-") + QSysInfo::buildAbi() + QLatin1Char('/'); const QString sharedCachePath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation); + m_globalCacheDir = sharedCachePath + subPath; + m_localCacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + subPath; + if (!sharedCachePath.isEmpty()) { - m_cacheDir = sharedCachePath + subPath; - m_cacheWritable = qt_ensureWritableDir(m_cacheDir); + m_currentCacheDir = m_globalCacheDir; + m_cacheWritable = qt_ensureWritableDir(m_currentCacheDir); } if (!m_cacheWritable) { - m_cacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + subPath; - m_cacheWritable = qt_ensureWritableDir(m_cacheDir); + m_currentCacheDir = m_localCacheDir; + m_cacheWritable = qt_ensureWritableDir(m_currentCacheDir); } - qCDebug(lcOpenGLProgramDiskCache, "Cache location '%s' writable = %d", qPrintable(m_cacheDir), m_cacheWritable); + + qCDebug(lcOpenGLProgramDiskCache, "Cache location '%s' writable = %d", qPrintable(m_currentCacheDir), m_cacheWritable); } QString QOpenGLProgramBinaryCache::cacheFileName(const QByteArray &cacheKey) const { - return m_cacheDir + QString::fromUtf8(cacheKey); + return m_currentCacheDir + QString::fromUtf8(cacheKey); } #define BASE_HEADER_SIZE (int(4 * sizeof(quint32))) @@ -361,6 +365,25 @@ static inline void writeStr(uchar **p, const QByteArray &str) *p += str.size(); } +static inline bool writeFile(const QString &filename, const QByteArray &data) +{ +#if QT_CONFIG(temporaryfile) + QSaveFile f(filename); + if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + f.write(data); + if (f.commit()) + return true; + } +#else + QFile f(filename); + if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + if (f.write(data) == data.length()) + return true; + } +#endif + return false; +} + void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId) { if (!m_cacheWritable) @@ -427,20 +450,20 @@ void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId) writeUInt(&blobFormatPtr, blobFormat); -#if QT_CONFIG(temporaryfile) - QSaveFile f(cacheFileName(cacheKey)); - if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - f.write(blob); - if (!f.commit()) -#else - QFile f(cacheFileName(cacheKey)); - if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - if (f.write(blob) < blob.length()) -#endif - qCDebug(lcOpenGLProgramDiskCache, "Failed to write %s to shader cache", qPrintable(f.fileName())); - } else { - qCDebug(lcOpenGLProgramDiskCache, "Failed to create %s in shader cache", qPrintable(f.fileName())); + QString filename = cacheFileName(cacheKey); + bool ok = writeFile(filename, blob); + if (!ok && m_currentCacheDir == m_globalCacheDir) { + m_currentCacheDir = m_localCacheDir; + m_cacheWritable = qt_ensureWritableDir(m_currentCacheDir); + qCDebug(lcOpenGLProgramDiskCache, "Cache location changed to '%s' writable = %d", + qPrintable(m_currentCacheDir), m_cacheWritable); + if (m_cacheWritable) { + filename = cacheFileName(cacheKey); + ok = writeFile(filename, blob); + } } + if (!ok) + qCDebug(lcOpenGLProgramDiskCache, "Failed to write %s to shader cache", qPrintable(filename)); } #if QT_CONFIG(opengles2) -- cgit v1.2.3