diff options
author | Pierre Ossman <ossman@cendio.se> | 2012-01-23 15:54:11 +0000 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2012-01-23 15:54:11 +0000 |
commit | 559a2e8f471edb9142eea892acc101d6fc58f0d6 (patch) | |
tree | 21efcef13a2cb0524019ab4cc0400dc1d9e2f079 /common/rfb | |
parent | 2f4fd6b9203f0ade624ff8500c3a8a8c8711db61 (diff) | |
download | tigervnc-559a2e8f471edb9142eea892acc101d6fc58f0d6.tar.gz tigervnc-559a2e8f471edb9142eea892acc101d6fc58f0d6.zip |
Fix a race condition where we might get updates thrown at us right after a
framebuffer switch, but before we've been given the pointer to the new
framebuffer.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4839 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'common/rfb')
-rw-r--r-- | common/rfb/VNCServer.h | 7 | ||||
-rw-r--r-- | common/rfb/VNCServerST.cxx | 27 | ||||
-rw-r--r-- | common/rfb/VNCServerST.h | 3 |
3 files changed, 36 insertions, 1 deletions
diff --git a/common/rfb/VNCServer.h b/common/rfb/VNCServer.h index 4e554792..280b68b4 100644 --- a/common/rfb/VNCServer.h +++ b/common/rfb/VNCServer.h @@ -30,6 +30,13 @@ namespace rfb { class VNCServer : public UpdateTracker { public: + // blockUpdates()/unblockUpdates() tells the server that the pixel buffer + // is currently in flux and may not be accessed. The attributes of the + // pixel buffer may still be accessed, but not the frame buffer itself. + // Note that access must be unblocked the exact same number of times it + // was blocked. + virtual void blockUpdates() = 0; + virtual void unblockUpdates() = 0; // setPixelBuffer() tells the server to use the given pixel buffer (and // optionally a modified screen layout). If this differs in size from diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx index 697695d4..b07f5c35 100644 --- a/common/rfb/VNCServerST.cxx +++ b/common/rfb/VNCServerST.cxx @@ -47,6 +47,7 @@ // otherwise blacklisted connections might be "forgotten". +#include <assert.h> #include <stdlib.h> #include <rfb/ServerCore.h> @@ -77,7 +78,8 @@ rfb::BoolParameter alwaysSetDeferUpdateTimer("AlwaysSetDeferUpdateTimer", // -=- Constructors/Destructor VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_) - : blHosts(&blacklist), desktop(desktop_), desktopStarted(false), pb(0), + : blHosts(&blacklist), desktop(desktop_), desktopStarted(false), + blockCounter(0), pb(0), name(strDup(name_)), pointerClient(0), comparer(0), renderedCursorInvalid(false), queryConnectionHandler(0), keyRemapper(&KeyRemapper::defInstance), @@ -259,6 +261,22 @@ int VNCServerST::checkTimeouts() // VNCServer methods +void VNCServerST::blockUpdates() +{ + blockCounter++; +} + +void VNCServerST::unblockUpdates() +{ + assert(blockCounter > 0); + + blockCounter--; + + // Flush out any updates we might have blocked + if (blockCounter == 0) + tryUpdate(); +} + void VNCServerST::setPixelBuffer(PixelBuffer* pb_, const ScreenSet& layout) { pb = pb_; @@ -545,6 +563,9 @@ void VNCServerST::tryUpdate() { std::list<VNCSConnectionST*>::iterator ci, ci_next; + if (blockCounter > 0) + return; + if (!checkDefer()) return; @@ -571,6 +592,10 @@ bool VNCServerST::checkUpdate() if (ui.is_empty() && !(renderCursor && renderedCursorInvalid)) return true; + // Block clients as the frame buffer cannot be safely accessed + if (blockCounter > 0) + return false; + // Block client from updating if we are currently deferring updates if (!checkDefer()) return false; diff --git a/common/rfb/VNCServerST.h b/common/rfb/VNCServerST.h index 2fed0a87..e75954fc 100644 --- a/common/rfb/VNCServerST.h +++ b/common/rfb/VNCServerST.h @@ -82,6 +82,8 @@ namespace rfb { // Methods overridden from VNCServer + virtual void blockUpdates(); + virtual void unblockUpdates(); virtual void setPixelBuffer(PixelBuffer* pb, const ScreenSet& layout); virtual void setPixelBuffer(PixelBuffer* pb); virtual void setScreenLayout(const ScreenSet& layout); @@ -209,6 +211,7 @@ namespace rfb { SDesktop* desktop; bool desktopStarted; + int blockCounter; PixelBuffer* pb; ScreenSet screenLayout; |