diff --git a/src/lib/client/Client.cpp b/src/lib/client/Client.cpp index 33048807..d50d1737 100644 --- a/src/lib/client/Client.cpp +++ b/src/lib/client/Client.cpp @@ -271,29 +271,38 @@ Client::leave() m_active = false; if (m_sendClipboardThread != NULL) { - StreamChunker::interruptClipboard(); + StreamChunker::setClipboardInterrupt(true); m_sendClipboardThread->wait(); + delete m_sendClipboardThread; m_sendClipboardThread = NULL; - } - - m_condData = false; - m_sendClipboardThread = new Thread( - new TMethodJob( - this, - &Client::sendClipboardThread, - NULL)); - // Bug #4735 - we can't leave() until fillClipboard()s all finish - Stopwatch timer(false); - m_mutex->lock(); - while (!m_condData) { - if (!m_condVar->wait(timer, 0.5)) { - LOG((CLOG_WARN "timed out %fs waiting for clipboard fill", - (double) timer.getTime())); - break; + StreamChunker::setClipboardInterrupt(false); + for (ClipboardID id = 0; id < kClipboardEnd; ++id) { + if (m_ownClipboard[id]) { + m_sentClipboard[id] = false; + } } - LOG((CLOG_DEBUG1 "leave %fs elapsed", (double) timer.getTime())); } - m_mutex->unlock(); + + if (m_sendClipboardThread == NULL) { + m_condData = false; + m_sendClipboardThread = new Thread( + new TMethodJob( + this, + &Client::sendClipboardThread, + NULL)); + // Bug #4735 - we can't leave() until fillClipboard()s all finish + Stopwatch timer(false); + m_mutex->lock(); + while (!m_condData) { + if (!m_condVar->wait(timer, 0.5)) { + LOG((CLOG_WARN "timed out %fs waiting for clipboard fill", + (double) timer.getTime())); + break; + } + LOG((CLOG_DEBUG1 "leave %fs elapsed", (double) timer.getTime())); + } + m_mutex->unlock(); + } m_screen->leave(); @@ -301,7 +310,7 @@ Client::leave() m_receivedFileData.clear(); LOG((CLOG_DEBUG "file transmission interrupted")); } - + return true; } diff --git a/src/lib/client/ServerProxy.cpp b/src/lib/client/ServerProxy.cpp index 9c2b9c75..16459b43 100644 --- a/src/lib/client/ServerProxy.cpp +++ b/src/lib/client/ServerProxy.cpp @@ -364,8 +364,6 @@ ServerProxy::onClipboardChanged(ClipboardID id, const IClipboard* clipboard) LOG((CLOG_DEBUG "sending clipboard %d seqnum=%d", id, m_seqNum)); StreamChunker::sendClipboard(data, data.size(), id, m_seqNum, m_events, this); - - LOG((CLOG_DEBUG "sent clipboard size=%d", data.size())); } void diff --git a/src/lib/server/ClientProxy1_6.cpp b/src/lib/server/ClientProxy1_6.cpp index bdd0f23f..b4c33e82 100644 --- a/src/lib/server/ClientProxy1_6.cpp +++ b/src/lib/server/ClientProxy1_6.cpp @@ -58,8 +58,6 @@ ClientProxy1_6::setClipboard(ClipboardID id, const IClipboard* clipboard) LOG((CLOG_DEBUG "sending clipboard %d to \"%s\"", id, getName().c_str())); StreamChunker::sendClipboard(data, size, id, 0, m_events, this); - - LOG((CLOG_DEBUG "sent clipboard size=%d", size)); } } diff --git a/src/lib/server/Server.cpp b/src/lib/server/Server.cpp index 3c9114e4..1f3bf3b2 100644 --- a/src/lib/server/Server.cpp +++ b/src/lib/server/Server.cpp @@ -509,9 +509,11 @@ Server::switchScreen(BaseClientProxy* dst, // if already sending clipboard, we need to interupt it, otherwise // clipboard data could be corrupted on the other side if (m_sendClipboardThread != NULL) { - StreamChunker::interruptClipboard(); + StreamChunker::setClipboardInterrupt(true); m_sendClipboardThread->wait(); + delete m_sendClipboardThread; m_sendClipboardThread = NULL; + StreamChunker::setClipboardInterrupt(false); } // send the clipboard data to new active screen diff --git a/src/lib/synergy/StreamChunker.cpp b/src/lib/synergy/StreamChunker.cpp index 380a37a3..d54839f3 100644 --- a/src/lib/synergy/StreamChunker.cpp +++ b/src/lib/synergy/StreamChunker.cpp @@ -17,6 +17,8 @@ #include "synergy/StreamChunker.h" +#include "mt/Lock.h" +#include "mt/Mutex.h" #include "synergy/FileChunk.h" #include "synergy/ClipboardChunk.h" #include "synergy/protocol_types.h" @@ -43,7 +45,7 @@ bool StreamChunker::s_isChunkingClipboard = false; bool StreamChunker::s_interruptClipboard = false; bool StreamChunker::s_isChunkingFile = false; bool StreamChunker::s_interruptFile = false; - +Mutex* StreamChunker::s_interruptMutex = NULL; void StreamChunker::sendFile( @@ -144,10 +146,15 @@ StreamChunker::sendClipboard( sendStopwatch.start(); while (true) { - if (s_interruptClipboard) { - s_interruptClipboard = false; - LOG((CLOG_DEBUG "clipboard transmission interrupted")); - break; + { + if (s_interruptMutex == NULL) { + s_interruptMutex = new Mutex(); + } + Lock lock(s_interruptMutex); + if (s_interruptClipboard) { + LOG((CLOG_DEBUG "clipboard transmission interrupted")); + break; + } } if (sendStopwatch.getTime() > SEND_THRESHOLD) { @@ -177,6 +184,8 @@ StreamChunker::sendClipboard( events->addEvent(Event(events->forClipboard().clipboardSending(), eventTarget, end)); + LOG((CLOG_DEBUG "sent clipboard size=%d", sentLength)); + s_isChunkingClipboard = false; } @@ -201,10 +210,24 @@ StreamChunker::interruptFile() } void -StreamChunker::interruptClipboard() +StreamChunker::setClipboardInterrupt(bool interrupt) { - if (s_isChunkingClipboard) { - s_interruptClipboard = true; - LOG((CLOG_INFO "previous clipboard data has become invalid")); + if (s_interruptMutex == NULL) { + s_interruptMutex = new Mutex(); + } + Lock lock(s_interruptMutex); + + if (interrupt) { + if (s_isChunkingClipboard) { + s_interruptClipboard = interrupt; + LOG((CLOG_INFO "previous clipboard data has become invalid")); + } + else { + LOG((CLOG_DEBUG "no clipboard to interrupt")); + } + } + else { + s_interruptClipboard = interrupt; + LOG((CLOG_DEBUG "reset clipboard interrupt")); } } diff --git a/src/lib/synergy/StreamChunker.h b/src/lib/synergy/StreamChunker.h index b0bfb341..cca9442b 100644 --- a/src/lib/synergy/StreamChunker.h +++ b/src/lib/synergy/StreamChunker.h @@ -21,6 +21,7 @@ #include "base/String.h" class IEventQueue; +class Mutex; class StreamChunker { public: @@ -37,7 +38,7 @@ public: void* eventTarget); static void updateChunkSize(bool useSecureSocket); static void interruptFile(); - static void interruptClipboard(); + static void setClipboardInterrupt(bool interrupt); private: static size_t s_chunkSize; @@ -45,4 +46,5 @@ private: static bool s_interruptClipboard; static bool s_isChunkingFile; static bool s_interruptFile; + static Mutex* s_interruptMutex; };