message: Fix deadlock in wait_test. Add testcase to reproduce that consistently.
diff: @@ -39,9 +39,15 @@ class ThreadCountingUpToValue {
  condvar_(condvar),
  mutex_(mutex) {}
  void operator()() {
  + // end_value_==-1 is how the master thread will tell us it's OK to terminate
  while (end_value_.load() != -1) {
  + // wait until end_value is set to a higher value
  + while (value_->load() == end_value_.load()) {
  + }
  + // increment value as long as it's lower than end_value
  while (value_->fetch_add(1) < end_value_.load() - 1) {
  }
  + // when value has reached end_value, notify the master thread.
  while (value_->load() == end_value_.load()) {
  std::lock_guard<std::mutex> lock(*mutex_);
  condvar_->notify_all();
  @@ -56,13 +62,14 @@ class ThreadCountingUpToValue {
  std::mutex* mutex_;
  };
  -void WaitTest(const Duration& spin_duration) {
  +void WaitTest(const Duration& spin_duration, const Duration& delay) {
  std::condition_variable condvar;
  std::mutex mutex;
  std::atomic<int> value(0);
  std::atomic<int> end_value(0);
  ThreadCountingUpToValue thread_callable(end_value, &value, &condvar, &mutex);
  std::thread thread(thread_callable);
  + std::this_thread::sleep_for(delay);
  for (int i = 1; i < 10; i++) {
  end_value.store(1000 * i);
  const auto& condition = [&value, &end_value]() {
  @@ -75,17 +82,26 @@ void WaitTest(const Duration& spin_duration) {
  thread.join();
  }
  -TEST(WaitTest, WaitTestNoSpin) { WaitTest(DurationFromSeconds(0)); }
  +TEST(WaitTest, WaitTestNoSpin) {
  + WaitTest(DurationFromSeconds(0), DurationFromSeconds(0));
  +}
  TEST(WaitTest, WaitTestSpinOneMicrosecond) {
  - WaitTest(DurationFromSeconds(1e-6));
  + WaitTest(DurationFromSeconds(1e-6), DurationFromSeconds(0));
  }
  TEST(WaitTest, WaitTestSpinOneMillisecond) {
  - WaitTest(DurationFromSeconds(1e-3));
  + WaitTest(DurationFromSeconds(1e-3), DurationFromSeconds(0));
  }
  -TEST(WaitTest, WaitTestSpinOneSecond) { WaitTest(DurationFromSeconds(1)); }
  +TEST(WaitTest, WaitTestSpinOneSecond) {
  + WaitTest(DurationFromSeconds(1), DurationFromSeconds(0));
  +}
  +
  +// Testcase to consistently reproduce the hang in b/139062384.
  +TEST(WaitTest, WaitTestNoSpinWithDelayBug139062384) {
  + WaitTest(DurationFromSeconds(0), DurationFromSeconds(1));
  +}
  } // namespace
  } // namespace ruy
  