HWInterface::Cursor() and therefor Desktop::Cursor() accessed the

current cursor without locking, and did not add a reference while
using the cursor. I have tried to solve both problems by introducing
a simple ServerCursorReference class, which makes sure that the
reference count is properly maintained. There are only two places
where this code was even used, from within ServerApp and when taking
screenshots. Axel, you mentioned in #837 that the code is unsafe, is
this what you meant? This hopefully fixes #837, but it is very hard
to reproduce in the first place, I will close the ticket, but it should
just be reopened if ever encountered again.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24741 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2008-04-02 11:12:39 +00:00
parent 42cf275606
commit ace2d5ee37
7 changed files with 91 additions and 30 deletions

View File

@ -714,15 +714,15 @@ Desktop::SetCursor(ServerCursor* newCursor)
if (newCursor == NULL)
newCursor = fCursorManager.GetCursor(B_CURSOR_DEFAULT);
ServerCursor* oldCursor = Cursor();
if (newCursor == oldCursor)
ServerCursorReference oldCursor = Cursor();
if (newCursor == oldCursor.Cursor())
return;
HWInterface()->SetCursor(newCursor);
}
ServerCursor*
ServerCursorReference
Desktop::Cursor() const
{
return HWInterface()->Cursor();

View File

@ -12,12 +12,13 @@
#include "CursorManager.h"
#include "DesktopSettings.h"
#include "EventDispatcher.h"
#include "MessageLooper.h"
#include "Screen.h"
#include "ScreenManager.h"
#include "ServerCursor.h"
#include "VirtualScreen.h"
#include "DesktopSettings.h"
#include "MessageLooper.h"
#include "WindowList.h"
#include "Workspace.h"
#include "WorkspacePrivate.h"
@ -78,7 +79,7 @@ class Desktop : public MessageLooper, public ScreenOwner {
CursorManager& GetCursorManager() { return fCursorManager; }
void SetCursor(ServerCursor* cursor);
ServerCursor* Cursor() const;
ServerCursorReference Cursor() const;
void SetLastMouseState(const BPoint& position,
int32 buttons);
// for use by the mouse filter only

View File

@ -291,8 +291,6 @@ ServerApp::Activate(bool value)
if (fIsActive == value)
return;
// TODO: send some message to the client?!?
fIsActive = value;
if (fIsActive) {

View File

@ -70,4 +70,54 @@ class ServerCursor : public ServerBitmap {
vint32 fPendingViewCursor;
};
class ServerCursorReference {
public:
ServerCursorReference()
: fCursor(NULL)
{
}
ServerCursorReference(ServerCursor* cursor)
: fCursor(cursor)
{
if (fCursor)
fCursor->Acquire();
}
ServerCursorReference(const ServerCursorReference& other)
: fCursor(other.fCursor)
{
if (fCursor)
fCursor->Acquire();
}
virtual ~ServerCursorReference()
{
if (fCursor)
fCursor->Release();
}
ServerCursorReference& operator=(const ServerCursorReference& other)
{
SetCursor(other.fCursor);
return *this;
}
void SetCursor(ServerCursor* cursor)
{
if (fCursor == cursor)
return;
if (fCursor)
fCursor->Release();
fCursor = cursor;
if (fCursor)
fCursor->Acquire();
}
ServerCursor* Cursor() const
{
return fCursor;
}
private:
ServerCursor* fCursor;
};
#endif // SERVER_CURSOR_H

View File

@ -1155,7 +1155,10 @@ DrawingEngine::ReadBitmap(ServerBitmap *bitmap, bool drawCursor, BRect bounds)
bounds.IntegerWidth() + 1, bounds.IntegerHeight() + 1);
if (drawCursor) {
ServerCursor *cursor = fGraphicsCard->Cursor();
ServerCursorReference cursorRef = fGraphicsCard->Cursor();
ServerCursor* cursor = cursorRef.Cursor();
if (!cursor)
return result;
int32 cursorWidth = cursor->Width();
int32 cursorHeight = cursor->Height();

View File

@ -12,7 +12,6 @@
#include "drawing_support.h"
#include "RenderingBuffer.h"
#include "ServerCursor.h"
#include "SystemPalette.h"
#include "UpdateQueue.h"
@ -148,6 +147,17 @@ HWInterface::SetCursor(ServerCursor* cursor)
fFloatingOverlaysLock.Unlock();
}
// Cursor
ServerCursorReference
HWInterface::Cursor() const
{
if (!fFloatingOverlaysLock.Lock())
return ServerCursorReference(NULL);
ServerCursorReference reference(fCursor);
fFloatingOverlaysLock.Unlock();
return reference;
}
// SetCursorVisible
void
HWInterface::SetCursorVisible(bool visible)

View File

@ -9,7 +9,9 @@
#define HW_INTERFACE_H
#include "IntRect.h"
#include "MultiLocker.h"
#include "ServerCursor.h"
#include <video_overlay.h>
@ -20,13 +22,10 @@
#include <OS.h>
#include <Region.h>
#include "IntRect.h"
class Overlay;
class RenderingBuffer;
class ServerBitmap;
class ServerCursor;
class UpdateQueue;
class BString;
@ -108,7 +107,7 @@ class HWInterface : protected MultiLocker {
virtual void Sync() {}
// cursor handling (these do their own Read/Write locking)
ServerCursor* Cursor() const { return fCursor; }
ServerCursorReference Cursor() const;
virtual void SetCursor(ServerCursor* cursor);
virtual void SetCursorVisible(bool visible);
bool IsCursorVisible();