[9.0.2] Fix infinite spin-wait and missing cancellation propagation in TaskDeduplicator. (https://github.com/bazelbuild/bazel/pull/28938) (#28990)

The test
TaskDeduplicatorTest.executeIfNeeded_executeAndCancelLoop_noErrors
sporadically hung during the ExecutorService.close() call. This was due
to two issues:

1. In executeIfNew, if a thread encountered a RefcountedFuture that was
already canceled (refcount = 0), it would call Thread.yield() and
continue the while(true) loop. It relied on a listener attached to the
canceled future to eventually remove it from the map. However, when
using virtual threads, many threads could enter this spin loop
simultaneously, saturating the underlying carrier threads. This
prevented the listener from being scheduled, creating a deadlock where
the spinning threads never saw the entry removed.

2. RefcountedFuture was not propagating the cancel() call to its
delegate future. This meant that even if all callers canceled their
interest in a task, the task would continue to execute in the
background, wasting resources and increasing contention.

This PR makes the following changes:

1. executeIfNew and maybeJoinExecution are modified to explicitly call
inFlightTasks.remove(key, future) if retain() fails. This ensures the
spin loop is broken immediately by the next thread to encounter the
canceled future, rather than waiting for an asynchronous listener.

2. RefcountedFuture.cancel now calls
delegate.cancel(mayInterruptIfRunning) when the internal reference count
drops to zero.

3. Thread.yield() and the associated
@SuppressWarnings("ThreadPriorityCheck") are removed, as they are no
longer necessary.

Fixes #28302.

Closes #28938.

PiperOrigin-RevId: 883147973
Change-Id: I28c1db252573a4c39b1a9e53d32e218327340054

Commit
https://github.com/bazelbuild/bazel/commit/a0760f1a08aca117912b39b7ba0eda2be50d17ce

Co-authored-by: Tiago Quelhas <tjgq@google.com>
1 file changed
tree: b4ddbbcd921fd359df2f6794092fe01ab9a52b41
  1. .bazelci/
  2. .github/
  3. docs/
  4. examples/
  5. scripts/
  6. site/
  7. src/
  8. third_party/
  9. tools/
  10. .bazelrc
  11. .bazelversion
  12. .gitattributes
  13. .gitignore
  14. AUTHORS
  15. bazel_downloader.cfg
  16. BUILD
  17. CHANGELOG.md
  18. CODE_OF_CONDUCT.md
  19. CODEOWNERS
  20. combine_distfiles.py
  21. combine_distfiles_to_tar.sh
  22. compile.sh
  23. CONTRIBUTING.md
  24. CONTRIBUTORS
  25. distdir.bzl
  26. extensions.bzl
  27. LICENSE
  28. maven_install.json
  29. MODULE.bazel
  30. MODULE.bazel.lock
  31. README.md
  32. repositories.bzl
  33. requirements.txt
  34. SECURITY.md
README.md

Bazel

{Fast, Correct} - Choose two

Build and test software of any size, quickly and reliably.

  • Speed up your builds and tests: Bazel rebuilds only what is necessary. With advanced local and distributed caching, optimized dependency analysis and parallel execution, you get fast and incremental builds.

  • One tool, multiple languages: Build and test Java, C++, Android, iOS, Go, and a wide variety of other language platforms. Bazel runs on Windows, macOS, and Linux.

  • Scalable: Bazel helps you scale your organization, codebase, and continuous integration solution. It handles codebases of any size, in multiple repositories or a huge monorepo.

  • Extensible to your needs: Easily add support for new languages and platforms with Bazel's familiar extension language. Share and re-use language rules written by the growing Bazel community.

Getting Started

Documentation

Reporting a Vulnerability

To report a security issue, please email security@bazel.build with a description of the issue, the steps you took to create the issue, affected versions, and, if known, mitigations for the issue. Our vulnerability management team will respond within 3 working days of your email. If the issue is confirmed as a vulnerability, we will open a Security Advisory. This project follows a 90 day disclosure timeline.

Contributing to Bazel

See CONTRIBUTING.md

Build status