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:
parent
1fde0f3e71
commit
8f0530c507
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue