Add retry to CondVarBase wait(), make sure Stopwatch is started on construction (Issue #4735)

* ArchMultithreadPosix::waitCondVar() returns every 100ms, so retry until we
  hit timeout.

* Stopwatch constructor should be called with "false" (not "true") to make sure
  Stopwatch is actually running when instantiated.
This commit is contained in:
Nye Liu 2015-09-11 10:42:01 -07:00 committed by Xinyu Hou
parent 1fde0f3e71
commit 8f0530c507
3 changed files with 18 additions and 10 deletions

View File

@ -283,13 +283,15 @@ Client::leave()
&Client::sendClipboardThread, &Client::sendClipboardThread,
NULL)); NULL));
// Bug #4735 - we can't leave() until fillClipboard()s all finish // Bug #4735 - we can't leave() until fillClipboard()s all finish
Stopwatch timer(true); Stopwatch timer(false);
m_mutex->lock(); m_mutex->lock();
while (!m_condData) { while (!m_condData) {
if (!m_condVar->wait(timer, 0.5)) { if (!m_condVar->wait(timer, 0.5)) {
LOG((CLOG_DEBUG "timed out waiting for clipboard fill")); LOG((CLOG_WARN "timed out %fs waiting for clipboard fill",
(double) timer.getTime()));
break; break;
} }
LOG((CLOG_DEBUG1 "leave %fs elapsed", (double) timer.getTime()));
} }
m_mutex->unlock(); m_mutex->unlock();
@ -789,6 +791,7 @@ Client::onFileRecieveCompleted()
void void
Client::sendClipboardThread(void * data) Client::sendClipboardThread(void * data)
{ {
Stopwatch timer(false);
Clipboard clipboard[kClipboardEnd]; Clipboard clipboard[kClipboardEnd];
// fill clipboards that we own and that have changed // fill clipboards that we own and that have changed
for (ClipboardID id = 0; id < kClipboardEnd; ++id) { for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
@ -796,6 +799,7 @@ Client::sendClipboardThread(void * data)
fillClipboard(id, &clipboard[id]); fillClipboard(id, &clipboard[id]);
} }
} }
LOG((CLOG_DEBUG1 "fill took %fs, signaling", (double) timer.getTime()));
// signal that fill is done // signal that fill is done
m_mutex->lock(); m_mutex->lock();
@ -811,6 +815,7 @@ Client::sendClipboardThread(void * data)
} }
m_sendClipboardThread = NULL; m_sendClipboardThread = NULL;
LOG((CLOG_DEBUG1 "send took %fs", (double) timer.getTime()));
} }
void void

View File

@ -63,13 +63,15 @@ CondVarBase::broadcast()
bool bool
CondVarBase::wait(Stopwatch& timer, double timeout) const CondVarBase::wait(Stopwatch& timer, double timeout) const
{ {
// check timeout against timer double remain = timeout-timer.getTime();
if (timeout >= 0.0) { // Some ARCH wait()s return prematurely, retry until really timed out
timeout -= timer.getTime(); // In particular, ArchMultithreadPosix::waitCondVar() returns every 100ms
if (timeout < 0.0) while (remain >= 0.0) {
return false; if (wait(remain))
return true;
remain = timeout - timer.getTime();
} }
return wait(timeout); return false;
} }
bool bool

View File

@ -513,6 +513,7 @@ XWindowsClipboard::icccmFillCache()
LOG((CLOG_DEBUG1 "selection doesn't support TARGETS")); LOG((CLOG_DEBUG1 "selection doesn't support TARGETS"));
data = ""; data = "";
XWindowsUtil::appendAtomData(data, XA_STRING); XWindowsUtil::appendAtomData(data, XA_STRING);
// return; // NTL
} }
XWindowsUtil::convertAtomProperty(data); XWindowsUtil::convertAtomProperty(data);
@ -1317,7 +1318,7 @@ XWindowsClipboard::CICCCMGetClipboard::readClipboard(Display* display,
// by badly behaved selection owners. // by badly behaved selection owners.
XEvent xevent; XEvent xevent;
std::vector<XEvent> events; std::vector<XEvent> events;
Stopwatch timeout(true); Stopwatch timeout(false); // timer not stopped, not triggered
static const double s_timeout = 0.25; // FIXME -- is this too short? static const double s_timeout = 0.25; // FIXME -- is this too short?
bool noWait = false; bool noWait = false;
while (!m_done && !m_failed) { while (!m_done && !m_failed) {
@ -1361,7 +1362,7 @@ XWindowsClipboard::CICCCMGetClipboard::readClipboard(Display* display,
XSelectInput(display, m_requestor, attr.your_event_mask); XSelectInput(display, m_requestor, attr.your_event_mask);
// return success or failure // return success or failure
LOG((CLOG_DEBUG1 "request %s", m_failed ? "failed" : "succeeded")); LOG((CLOG_DEBUG1 "request %s after %fs", m_failed ? "failed" : "succeeded", timeout.getTime()));
return !m_failed; return !m_failed;
} }