Skip to content

Fixing EndpointPool concurrency issues - #690

Open
Myllyenko wants to merge 1 commit into
ydb-platform:masterfrom
Myllyenko:fix/endpoint-pool-locking
Open

Fixing EndpointPool concurrency issues#690
Myllyenko wants to merge 1 commit into
ydb-platform:masterfrom
Myllyenko:fix/endpoint-pool-locking

Conversation

@Myllyenko

Copy link
Copy Markdown

pessimizeEndpoint looked up recordsByEndpoint and tested knownEndpoint.isPessimized() before taking any lock. Both the map reference and the priority field it reads are non-volatile and are replaced or written under the write lock by setNewState and pessimize, so those reads had no happens-before edge with the writers. Two threads failing on the same endpoint could each miss the other's update and redo the full re-sort and rescan of the pool, and a lookup against a stale map could pessimize an entry that is no longer part of the current state.

needToRunDiscovery is written under the write lock but read by the discovery scheduler thread with no lock at all, so a pessimization-driven discovery could go unnoticed indefinitely.

pessimizeEndpoint looked up recordsByEndpoint and tested
knownEndpoint.isPessimized() before taking any lock. Both the map
reference and the priority field it reads are non-volatile and are
replaced or written under the write lock by setNewState and pessimize, so
those reads had no happens-before edge with the writers. Two threads
failing on the same endpoint could each miss the other's update and
redo the full re-sort and rescan of the pool, and a lookup against a
stale map could pessimize an entry that is no longer part of the current
state.

Keep the cheap "already pessimized" short circuit but perform it under the
read lock, then re-validate under the write lock before mutating.

needToRunDiscovery is written under the write lock but read by the
discovery scheduler thread with no lock at all, so a pessimization-driven
discovery could go unnoticed indefinitely. Make it volatile.

This is a memory visibility fix; the interleavings involved are not
reproducible deterministically, so it comes without a new test.
@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.33333% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.91%. Comparing base (d876581) to head (601216e).

Files with missing lines Patch % Lines
...ain/java/tech/ydb/core/impl/pool/EndpointPool.java 83.33% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##             master     #690   +/-   ##
=========================================
  Coverage     71.91%   71.91%           
+ Complexity     3474     3473    -1     
=========================================
  Files           390      390           
  Lines         16220    16225    +5     
  Branches       1698     1699    +1     
=========================================
+ Hits          11664    11669    +5     
  Misses         3904     3904           
  Partials        652      652           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant