app_server: fix race condition in alpha mask cloning

* Add a lock which is acquired when reattaching/regenerating masks,
  and also acquired for a cached mask before making a clone of it,
  to prevent the clone from having an inconsistent state in
  concurrent edge cases.

* Maybe fixes #12469
This commit is contained in:
Julian Harnath 2015-11-15 22:03:14 +01:00
parent 97921e3f43
commit 3c9d8d6460
2 changed files with 10 additions and 0 deletions

View File

@ -22,6 +22,8 @@
#include "Shape.h"
#include "ShapePrivate.h"
#include <AutoLocker.h>
// #pragma mark - AlphaMask
@ -103,6 +105,8 @@ AlphaMask::~AlphaMask()
IntPoint
AlphaMask::SetCanvasGeometry(IntPoint origin, IntRect bounds)
{
AutoLocker<BLocker> locker(fLock);
if (origin == fCanvasOrigin && bounds.Width() == fCanvasBounds.Width()
&& bounds.Height() == fCanvasBounds.Height())
return fCanvasOrigin;
@ -159,6 +163,8 @@ AlphaMask::_CreateTemporaryBitmap(BRect bounds) const
void
AlphaMask::_Generate()
{
AutoLocker<BLocker> locker(fLock);
ServerBitmap* const bitmap = _RenderSource(fCanvasBounds);
BReference<ServerBitmap> bitmapRef(bitmap, true);
if (bitmap == NULL) {
@ -484,6 +490,7 @@ ShapeAlphaMask::Create(AlphaMask* previousMask, const shape_data& shape,
// TODO: don't make a new mask if the cache entry has no drawstate
// using it anymore, because then we ca just immediately reuse it
AlphaMask* cachedMask = mask;
AutoLocker<BLocker> locker(mask->fLock);
mask = new(std::nothrow) ShapeAlphaMask(previousMask, mask);
cachedMask->ReleaseReference();
}

View File

@ -15,6 +15,8 @@
#include "drawing/Painter/defines.h"
#include "IntRect.h"
#include <Locker.h>
class BShape;
class ServerBitmap;
@ -63,6 +65,7 @@ protected:
BReference<AlphaMask> fPreviousMask;
IntRect fBounds;
bool fClippedToCanvas;
BLocker fLock;
private:
friend class AlphaMaskCache;