summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yurii Zubrytskyi <zyy@google.com> 2023-08-01 15:55:05 -0700
committer Yurii Zubrytskyi <zyy@google.com> 2023-08-01 15:55:05 -0700
commit67a1c1a79e4f2373b57a5c4c7173bb383ef75066 (patch)
tree59047d4a2c6323a941d50628113a168af995a2a6
parent8b2832873705d7d7c72d6082806ef5be524619f2 (diff)
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
-rw-r--r--services/incremental/ServiceWrappers.cpp15
1 files changed, 13 insertions, 2 deletions
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index ce3d51483d73..2a2fa7adf5cb 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -315,11 +315,22 @@ private:
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;
}