#4768 Interrupted both clipboards

This commit is contained in:
Jerry (Xinyu Hou) 2016-07-05 12:30:08 +01:00
parent 518fc7a676
commit 1a76acd446
6 changed files with 67 additions and 35 deletions

View File

@ -271,29 +271,38 @@ Client::leave()
m_active = false; m_active = false;
if (m_sendClipboardThread != NULL) { if (m_sendClipboardThread != NULL) {
StreamChunker::interruptClipboard(); StreamChunker::setClipboardInterrupt(true);
m_sendClipboardThread->wait(); m_sendClipboardThread->wait();
delete m_sendClipboardThread;
m_sendClipboardThread = NULL; m_sendClipboardThread = NULL;
} StreamChunker::setClipboardInterrupt(false);
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
m_condData = false; if (m_ownClipboard[id]) {
m_sendClipboardThread = new Thread( m_sentClipboard[id] = false;
new TMethodJob<Client>( }
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();
if (m_sendClipboardThread == NULL) {
m_condData = false;
m_sendClipboardThread = new Thread(
new TMethodJob<Client>(
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(); m_screen->leave();
@ -301,7 +310,7 @@ Client::leave()
m_receivedFileData.clear(); m_receivedFileData.clear();
LOG((CLOG_DEBUG "file transmission interrupted")); LOG((CLOG_DEBUG "file transmission interrupted"));
} }
return true; return true;
} }

View File

@ -364,8 +364,6 @@ ServerProxy::onClipboardChanged(ClipboardID id, const IClipboard* clipboard)
LOG((CLOG_DEBUG "sending clipboard %d seqnum=%d", id, m_seqNum)); LOG((CLOG_DEBUG "sending clipboard %d seqnum=%d", id, m_seqNum));
StreamChunker::sendClipboard(data, data.size(), id, m_seqNum, m_events, this); StreamChunker::sendClipboard(data, data.size(), id, m_seqNum, m_events, this);
LOG((CLOG_DEBUG "sent clipboard size=%d", data.size()));
} }
void void

View File

@ -58,8 +58,6 @@ ClientProxy1_6::setClipboard(ClipboardID id, const IClipboard* clipboard)
LOG((CLOG_DEBUG "sending clipboard %d to \"%s\"", id, getName().c_str())); LOG((CLOG_DEBUG "sending clipboard %d to \"%s\"", id, getName().c_str()));
StreamChunker::sendClipboard(data, size, id, 0, m_events, this); StreamChunker::sendClipboard(data, size, id, 0, m_events, this);
LOG((CLOG_DEBUG "sent clipboard size=%d", size));
} }
} }

View File

@ -509,9 +509,11 @@ Server::switchScreen(BaseClientProxy* dst,
// if already sending clipboard, we need to interupt it, otherwise // if already sending clipboard, we need to interupt it, otherwise
// clipboard data could be corrupted on the other side // clipboard data could be corrupted on the other side
if (m_sendClipboardThread != NULL) { if (m_sendClipboardThread != NULL) {
StreamChunker::interruptClipboard(); StreamChunker::setClipboardInterrupt(true);
m_sendClipboardThread->wait(); m_sendClipboardThread->wait();
delete m_sendClipboardThread;
m_sendClipboardThread = NULL; m_sendClipboardThread = NULL;
StreamChunker::setClipboardInterrupt(false);
} }
// send the clipboard data to new active screen // send the clipboard data to new active screen

View File

@ -17,6 +17,8 @@
#include "synergy/StreamChunker.h" #include "synergy/StreamChunker.h"
#include "mt/Lock.h"
#include "mt/Mutex.h"
#include "synergy/FileChunk.h" #include "synergy/FileChunk.h"
#include "synergy/ClipboardChunk.h" #include "synergy/ClipboardChunk.h"
#include "synergy/protocol_types.h" #include "synergy/protocol_types.h"
@ -43,7 +45,7 @@ bool StreamChunker::s_isChunkingClipboard = false;
bool StreamChunker::s_interruptClipboard = false; bool StreamChunker::s_interruptClipboard = false;
bool StreamChunker::s_isChunkingFile = false; bool StreamChunker::s_isChunkingFile = false;
bool StreamChunker::s_interruptFile = false; bool StreamChunker::s_interruptFile = false;
Mutex* StreamChunker::s_interruptMutex = NULL;
void void
StreamChunker::sendFile( StreamChunker::sendFile(
@ -144,10 +146,15 @@ StreamChunker::sendClipboard(
sendStopwatch.start(); sendStopwatch.start();
while (true) { while (true) {
if (s_interruptClipboard) { {
s_interruptClipboard = false; if (s_interruptMutex == NULL) {
LOG((CLOG_DEBUG "clipboard transmission interrupted")); s_interruptMutex = new Mutex();
break; }
Lock lock(s_interruptMutex);
if (s_interruptClipboard) {
LOG((CLOG_DEBUG "clipboard transmission interrupted"));
break;
}
} }
if (sendStopwatch.getTime() > SEND_THRESHOLD) { if (sendStopwatch.getTime() > SEND_THRESHOLD) {
@ -177,6 +184,8 @@ StreamChunker::sendClipboard(
events->addEvent(Event(events->forClipboard().clipboardSending(), eventTarget, end)); events->addEvent(Event(events->forClipboard().clipboardSending(), eventTarget, end));
LOG((CLOG_DEBUG "sent clipboard size=%d", sentLength));
s_isChunkingClipboard = false; s_isChunkingClipboard = false;
} }
@ -201,10 +210,24 @@ StreamChunker::interruptFile()
} }
void void
StreamChunker::interruptClipboard() StreamChunker::setClipboardInterrupt(bool interrupt)
{ {
if (s_isChunkingClipboard) { if (s_interruptMutex == NULL) {
s_interruptClipboard = true; s_interruptMutex = new Mutex();
LOG((CLOG_INFO "previous clipboard data has become invalid")); }
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"));
} }
} }

View File

@ -21,6 +21,7 @@
#include "base/String.h" #include "base/String.h"
class IEventQueue; class IEventQueue;
class Mutex;
class StreamChunker { class StreamChunker {
public: public:
@ -37,7 +38,7 @@ public:
void* eventTarget); void* eventTarget);
static void updateChunkSize(bool useSecureSocket); static void updateChunkSize(bool useSecureSocket);
static void interruptFile(); static void interruptFile();
static void interruptClipboard(); static void setClipboardInterrupt(bool interrupt);
private: private:
static size_t s_chunkSize; static size_t s_chunkSize;
@ -45,4 +46,5 @@ private:
static bool s_interruptClipboard; static bool s_interruptClipboard;
static bool s_isChunkingFile; static bool s_isChunkingFile;
static bool s_interruptFile; static bool s_interruptFile;
static Mutex* s_interruptMutex;
}; };