Fix timeouts for android::base::WaitForProperty*
std::chrono doesn't handle integer overflow, so using
std::chrono::milliseconds::max() to indicate an infinite timeout is
not handled well in the current code. It causes an 'absolute_timeout'
earlier in time than 'now' and causes the associated WaitForProperty*
functions to return immediately.
Also, any duration_cast from relative_timeout to nanoseconds would
cause the same issue, as it would overflow in the conversion and
result in an invalid results.
This change prevents any duration_casts of relative_timeout to
nanoseconds and replaces the logic to wait on an absolute timeout with
logic that compares the time elapsed to the provided relative timeout.
This change also includes a test that std::chrono::milliseconds::max()
does not return immediately and that negative values do return immediately.
Test: Boot bullhead + libbase_test
Change-Id: I335bfa7ba71e86c20119a0ed46014cad44361162
diff --git a/properties_test.cpp b/properties_test.cpp
index 1bbe482..de5f3dc 100644
--- a/properties_test.cpp
+++ b/properties_test.cpp
@@ -151,6 +151,38 @@
ASSERT_LT(std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0), 600ms);
}
+TEST(properties, WaitForProperty_MaxTimeout) {
+ std::atomic<bool> flag{false};
+ std::thread thread([&]() {
+ android::base::SetProperty("debug.libbase.WaitForProperty_test", "a");
+ while (!flag) std::this_thread::yield();
+ std::this_thread::sleep_for(500ms);
+ android::base::SetProperty("debug.libbase.WaitForProperty_test", "b");
+ });
+
+ ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "a", 1s));
+ flag = true;
+ // Test that this does not immediately return false due to overflow issues with the timeout.
+ ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b"));
+ thread.join();
+}
+
+TEST(properties, WaitForProperty_NegativeTimeout) {
+ std::atomic<bool> flag{false};
+ std::thread thread([&]() {
+ android::base::SetProperty("debug.libbase.WaitForProperty_test", "a");
+ while (!flag) std::this_thread::yield();
+ std::this_thread::sleep_for(500ms);
+ android::base::SetProperty("debug.libbase.WaitForProperty_test", "b");
+ });
+
+ ASSERT_TRUE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "a", 1s));
+ flag = true;
+ // Assert that this immediately returns with a negative timeout
+ ASSERT_FALSE(android::base::WaitForProperty("debug.libbase.WaitForProperty_test", "b", -100ms));
+ thread.join();
+}
+
TEST(properties, WaitForPropertyCreation) {
std::thread thread([&]() {
std::this_thread::sleep_for(100ms);