Skip to content

Conversation

@becomeStar
Copy link
Contributor

Fixes a race between newStream() and unregisterInbound() that could cause inconsistent transportInUse() notifications. The updates to numInUseStreams are now synchronized via updateInUseStreamsIfNeed(), ensuring listener state remains accurate.
Also replaced AtomicInteger with a primitive int since synchronization makes atomic operations unnecessary.

Fixes #10917

…ronizing in-use updates

Previously, concurrent calls to newStream() and unregisterInbound() could both
 update numInUseStreams and invoke transportInUse() in conflicting order,
 leading to inconsistent listener state. This change synchronizes updates and
 only notifies the listener on transitions between 0 and >0.

 Fixes grpc#10917
@becomeStar
Copy link
Contributor Author

becomeStar commented Oct 31, 2025

I’m considering adding a unit test for updateInUseStreamsIfNeed() (with VisibleForTesting annotation)
to verify its behavior on in-use state transitions.
Would you prefer this test to be included in the same PR or in a separate one?

@ejona86 ejona86 requested a review from jdcormie November 4, 2025 18:15
@GuardedBy("this")
void notifyTerminated() {
if (numInUseStreams.getAndSet(0) > 0) {
if(numInUseStreams > 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please format this code according to the style guide: https://google.github.io/styleguide/javaguide.html I recommend the https://github.com/google/google-java-format tool

if (inbound.countsForInUse() && numInUseStreams.decrementAndGet() == 0) {
clientTransportListener.transportInUse(false);
}
updateInUseStreamsIfNeed(inbound.countsForInUse(), -1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see "A note on synchronization" at the top of BinderTransport.java. Note that unregisterInbound() is called from Inbound.java's synchronized closeAbnormal() and deliverSuffix() methods (via unregister()) Is your proposed lock acquisition order safe or does it risk deadlock?

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.

binder: ManagedClientTransport.Listener invocations are not properly synchronized

2 participants