diff --git a/kdelibs-4.4.2-kpixmapcache.patch b/kdelibs-4.4.2-kpixmapcache.patch new file mode 100644 index 0000000..c7c6319 --- /dev/null +++ b/kdelibs-4.4.2-kpixmapcache.patch @@ -0,0 +1,167 @@ +--- kdelibs/kdeui/util/kpixmapcache.cpp 2010/03/17 02:34:11 1104230 ++++ kdelibs/kdeui/util/kpixmapcache.cpp 2010/03/17 02:38:08 1104231 +@@ -40,6 +40,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -633,6 +634,10 @@ + qint32 leftchild, rightchild; + stream >> fkey >> foffset >> timesused >> lastused >> leftchild >> rightchild; + ++ if (fkey.isEmpty()) { ++ return start; ++ } ++ + if (key < fkey) { + if (leftchild) { + return binarySearchKey(stream, key, leftchild); +@@ -660,12 +665,21 @@ + // exist yet and there are no entries. Otherwise, do a binary search + // starting from the root node. + if (!stream.atEnd()) { ++ // One exception is that the root node may exist but be invalid, ++ // which can happen when the cache data is discarded. This is ++ // represented by an empty fkey ++ QString fkey; ++ stream >> fkey; ++ ++ if (fkey.isEmpty()) { ++ delete device; ++ return -1; ++ } ++ + int nodeoffset = binarySearchKey(stream, key, mIndexRootOffset); + + // Load the found entry and check if it's the one we're looking for. + device->seek(nodeoffset); +- QString fkey; +- stream >> fkey; + if (fkey == key) { + // Read offset and statistics + qint32 foffset; +@@ -814,7 +828,9 @@ + QString fkey; + stream.device()->seek(parentoffset); + stream >> fkey; +- if (key == fkey) { ++ ++ // The key would be empty if the cache had been discarded. ++ if (key == fkey || fkey.isEmpty()) { + // We're overwriting an existing entry + offset = parentoffset; + } +@@ -1195,16 +1211,14 @@ + return false; + } + +- d->invalidateMmapFiles(); +- d->unmmapFiles(); +- +- d->mEnabled = false; +- + KPCLockFile lock(d->mLockFileName); + // Hope we got the lock... + ++ d->invalidateMmapFiles(); ++ d->mEnabled = false; ++ + // Create index file +- QFile indexfile(d->mIndexFile); ++ KSaveFile indexfile(d->mIndexFile); + if (!indexfile.open(QIODevice::WriteOnly)) { + kError() << "Couldn't create index file" << d->mIndexFile; + return false; +@@ -1212,7 +1226,7 @@ + + d->mCacheId = ::time(0); + d->mTimestamp = ::time(0); +- ++ + // We can't know the full size until custom headers written. + // mmapFiles() will take care of correcting the size. + KPixmapCacheIndexHeader indexHeader = { {0}, KPIXMAPCACHE_VERSION, 0, d->mCacheId, d->mTimestamp }; +@@ -1221,7 +1235,7 @@ + indexfile.write(reinterpret_cast(&indexHeader), sizeof indexHeader); + + // Create data file +- QFile datafile(d->mDataFile); ++ KSaveFile datafile(d->mDataFile); + if (!datafile.open(QIODevice::WriteOnly)) { + kError() << "Couldn't create data file" << d->mDataFile; + return false; +@@ -1243,40 +1257,54 @@ + // Close the files and mmap them (if mmapping is used) + indexfile.close(); + datafile.close(); ++ indexfile.finalize(); ++ datafile.finalize(); ++ + d->mEnabled = true; + d->mmapFiles(); ++ + return true; + } + + void KPixmapCache::deleteCache(const QString& name) + { +- foreach (KPixmapCache::Private *d, Private::mCaches) { +- if (d->mName == name && d->mInited) { +- d->q->discard(); +- } +- } ++ QString indexFile = KGlobal::dirs()->locateLocal("cache", "kpc/" + name + ".index"); ++ QString dataFile = KGlobal::dirs()->locateLocal("cache", "kpc/" + name + ".data"); ++ ++ QFile::remove(indexFile); ++ QFile::remove(dataFile); + } + + void KPixmapCache::discard() + { +- d->invalidateMmapFiles(); +- d->unmmapFiles(); +- d->mInited = false; ++ // To "discard" the cache we simply have to make sure that every that ++ // was in there before is no longer present when we search for them. ++ // Easiest way to do *that* is to simply delete the index. ++ ++ KPCLockFile lock(d->mLockFileName); ++ if(!lock.isValid()) { ++ kError(264) << "Unable to lock pixmap cache when trying to discard it"; ++ return; ++ } ++ ++ QIODevice *device = d->indexDevice(); ++ if (!device) { ++ kError(264) << "Unable to access index when trying to discard cache"; ++ return; ++ } ++ ++ device->seek(d->mIndexRootOffset); ++ QDataStream stream(device); ++ ++ // Stream an empty QString as the hash key to signify that the cache ++ // has been discarded. ++ stream << QString(); + + if (d->mUseQPixmapCache) { + // TODO: This is broken, it removes every cached QPixmap in the whole + // process, not just this KPixmapCache. + QPixmapCache::clear(); + } +- +- QString indexFile = KGlobal::dirs()->locateLocal("cache", "kpc/" + d->mName + ".index"); +- QString dataFile = KGlobal::dirs()->locateLocal("cache", "kpc/" + d->mName + ".data"); +- +- QFile::remove(indexFile); +- QFile::remove(dataFile); +- +- // No need to remove the lockfile +- d->init(); + } + + void KPixmapCache::removeEntries(int newsize) diff --git a/kdelibs.spec b/kdelibs.spec index 66abca9..75fc624 100644 --- a/kdelibs.spec +++ b/kdelibs.spec @@ -83,6 +83,8 @@ Patch24: kdelibs-4.3.1-drkonq.patch # paths (like /usr/lib64) already! With this, we can drop # -DCMAKE_SKIP_RPATH:BOOL=ON (finally) Patch27: kdelibs-4.3.98-no_rpath.patch +# bug:568389 (crash in kpixmapcache) +Patch28: kdelibs-4.4.2-kpixmapcache.patch # upstreamable @@ -231,6 +233,7 @@ format for easy browsing. %patch24 -p1 -b .drkonq %endif %patch27 -p1 -b .no_rpath +%patch28 -p1 -b .kpixmapcache # upstreamable patches @@ -426,6 +429,9 @@ rm -rf %{buildroot} %changelog +* Wed Mar 17 2010 Lukas Tinkl - 6:4.4.1-6 +- fix crash in KPixmapCache (bug#568389) + * Tue Mar 09 2010 Rex Dieter - 6:4.4.1-5 - rebuild (soprano)