From 4f113740180b6512b43723c4728f262882dc9b45 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 3 May 2011 16:21:41 -0700 Subject: [PATCH] Fix a race-condtion in SurfaceFlinger that could lead to a crash. Client::mLayers could be accessed from different threads. On one side from Client::attachLayer() which is currently called from a binder thread; on the other side from Client::detachLayer() which is always called from the main thread. This could lead to a corruption of Client::mLayers. We fix this issue by adding an internal lock to Client. Change-Id: Ib1317d7750ed5030e6f577efe34b69fc10198bd3 --- services/surfaceflinger/SurfaceFlinger.cpp | 20 ++++++++++++-------- services/surfaceflinger/SurfaceFlinger.h | 12 +++++++++--- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7506f298f..ad6ab8e45 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1094,15 +1094,15 @@ status_t SurfaceFlinger::addLayer_l(const sp& layer) ssize_t SurfaceFlinger::addClientLayer(const sp& client, const sp& lbc) { - Mutex::Autolock _l(mStateLock); - // attach this layer to the client - ssize_t name = client->attachLayer(lbc); + size_t name = client->attachLayer(lbc); + + Mutex::Autolock _l(mStateLock); // add this layer to the current state list addLayer_l(lbc); - return name; + return ssize_t(name); } status_t SurfaceFlinger::removeLayer(const sp& layer) @@ -2381,15 +2381,17 @@ status_t Client::initCheck() const { return NO_ERROR; } -ssize_t Client::attachLayer(const sp& layer) +size_t Client::attachLayer(const sp& layer) { - int32_t name = android_atomic_inc(&mNameGenerator); + Mutex::Autolock _l(mLock); + size_t name = mNameGenerator++; mLayers.add(name, layer); return name; } void Client::detachLayer(const LayerBaseClient* layer) { + Mutex::Autolock _l(mLock); // we do a linear search here, because this doesn't happen often const size_t count = mLayers.size(); for (size_t i=0 ; i Client::getLayerUser(int32_t i) const { +sp Client::getLayerUser(int32_t i) const +{ + Mutex::Autolock _l(mLock); sp lbc; - const wp& layer(mLayers.valueFor(i)); + wp layer(mLayers.valueFor(i)); if (layer != 0) { lbc = layer.promote(); LOGE_IF(lbc==0, "getLayerUser(name=%d) is dead", int(i)); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 1b36d1cd6..3eb4c115e 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -65,7 +65,7 @@ public: status_t initCheck() const; // protected by SurfaceFlinger::mStateLock - ssize_t attachLayer(const sp& layer); + size_t attachLayer(const sp& layer); void detachLayer(const LayerBaseClient* layer); sp getLayerUser(int32_t i) const; @@ -81,9 +81,15 @@ private: virtual status_t destroySurface(SurfaceID surfaceId); virtual status_t setState(int32_t count, const layer_state_t* states); - DefaultKeyedVector< size_t, wp > mLayers; + // constant sp mFlinger; - int32_t mNameGenerator; + + // protected by mLock + DefaultKeyedVector< size_t, wp > mLayers; + size_t mNameGenerator; + + // thread-safe + mutable Mutex mLock; }; class UserClient : public BnSurfaceComposerClient