Fix wait_until(infinity) for condition_variable
libcxx implements wait_until using wait_for, which in
its turn has to call a syscall that's basically wait_until,
causing a double conversion of the waiting time parameter.
Because of this, infinity detection code in those conversions
sometimes fail if the delat between the conversions is long
enough - causing a syscall error for 'invalid time'
This CL explicitly calls non-timed wait() instead.
Bug: 293223125
Bug: 292138960
Test: build + unit tests + presubmits
Change-Id: Id30fdfbe374b63fcaed627fcdf374f1e501a7807
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index ce3d514..2a2fa7a 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -315,11 +315,22 @@
std::unique_lock lock(mMutex);
for (;;) {
const TimePoint nextJobTs = mJobs.empty() ? kInfinityTs : mJobs.begin()->when;
- mCondition.wait_until(lock, nextJobTs, [this, oldNextJobTs = nextJobTs]() {
+ auto conditionPredicate = [this, oldNextJobTs = nextJobTs]() {
const auto now = Clock::now();
const auto newFirstJobTs = !mJobs.empty() ? mJobs.begin()->when : kInfinityTs;
return newFirstJobTs <= now || newFirstJobTs < oldNextJobTs || !mRunning;
- });
+ };
+ // libcxx's implementation of wait_until() recalculates the 'until' time into
+ // the wait duration and then goes back to the absolute timestamp when calling
+ // pthread_cond_timedwait(); this back-and-forth calculation sometimes loses
+ // the 'infinity' value because enough time passes in between, and instead
+ // passes incorrect timestamp into the syscall, causing a crash.
+ // Mitigating it by explicitly calling the non-timed wait here.
+ if (mJobs.empty()) {
+ mCondition.wait(lock, conditionPredicate);
+ } else {
+ mCondition.wait_until(lock, nextJobTs, conditionPredicate);
+ }
if (!mRunning) {
return;
}