Fix crash in QDeclarativePixmapStore global static dtor
authorChris Adams <christopher.adams@nokia.com>
Tue, 28 Feb 2012 04:04:38 +0000 (14:04 +1000)
committerQt by Nokia <qt-info@nokia.com>
Tue, 28 Feb 2012 04:37:43 +0000 (05:37 +0100)
Due to the undefined ordering of global static dtors, the QDPS dtor
could run after the texture factories were deleted.  Thus, the QDPS
dtor cannot call the cost() method of the pixmap data during its
destructor, as this could cause a crash.

Change-Id: I5d23066dc57e1992cf9d1c13d514f06c431bc752
Reviewed-by: Alan Alpert <alan.alpert@nokia.com>
src/declarative/qml/qdeclarativeimageprovider.h
src/quick/util/qdeclarativepixmapcache.cpp

index 55a5ca2..16af452 100644 (file)
@@ -58,7 +58,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeTextureFactory : public QObject
 {
 public:
     QDeclarativeTextureFactory();
-    ~QDeclarativeTextureFactory();
+    virtual ~QDeclarativeTextureFactory();
 
     virtual QSGTexture *createTexture(QQuickCanvas *canvas) const = 0;
     virtual QSize textureSize() const = 0;
index 95cbd36..1f187a7 100644 (file)
@@ -762,6 +762,8 @@ void QDeclarativePixmapStore::unreferencePixmap(QDeclarativePixmapData *data)
 
     data->nextUnreferenced = m_unreferencedPixmaps;
     data->prevUnreferencedPtr = &m_unreferencedPixmaps;
+    if (!m_destroying) // the texture factories may have been cleaned up already.
+        m_unreferencedCost += data->cost();
 
     m_unreferencedPixmaps = data;
     if (m_unreferencedPixmaps->nextUnreferenced) {
@@ -772,8 +774,6 @@ void QDeclarativePixmapStore::unreferencePixmap(QDeclarativePixmapData *data)
     if (!m_lastUnreferencedPixmap)
         m_lastUnreferencedPixmap = data;
 
-    m_unreferencedCost += data->cost();
-
     shrinkCache(-1); // Shrink the cache incase it has become larger than cache_limit
 
     if (m_timerId == -1 && m_unreferencedPixmaps && !m_destroying)
@@ -810,8 +810,10 @@ void QDeclarativePixmapStore::shrinkCache(int remove)
         data->prevUnreferencedPtr = 0;
         data->prevUnreferenced = 0;
 
-        remove -= data->cost();
-        m_unreferencedCost -= data->cost();
+        if (!m_destroying) {
+            remove -= data->cost();
+            m_unreferencedCost -= data->cost();
+        }
         data->removeFromCache();
         delete data;
     }