Skip to content

HTTPCLIENT-2379 - Handle duplicate release() safely in H2SharingConnPool #663

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 6, 2025

Conversation

arturobernalg
Copy link
Member

@arturobernalg arturobernalg commented Jul 2, 2025

Return early in H2SharingConnPool#release when the entry’s lease count is zero, so duplicate releases become no-ops and the underlying pool no longer throws IllegalStateException.

tested with https://github.com/yhzdys/httpcomponents-client/commit/c8256b33c3adb45cfa2a49efb2dacfb611da9ac1

@ok2c
Copy link
Member

ok2c commented Jul 3, 2025

@arturobernalg I am afraid this change-set fixes a side-effect and simply hides the underlying problem. As far as I remember (i am still reviewing my code) there should be no un-tracked pool entries for tracked routes.

@arturobernalg
Copy link
Member Author

arturobernalg commented Jul 3, 2025

I am afraid this change-set fixes a side-effect and simply hides the underlying problem. As far as I remember (i am still reviewing my code) there should be no un-tracked pool entries for tracked routes.

@ok2c the entry is dropped after the first release, and the second call tries to hand it back again, triggering the exception... i see. ..
That’s was my initial intent 2099b31 to fix this .

@@ -288,20 +290,14 @@ PoolEntry<T, C> lease() {
long release(final PoolEntry<T, C> entry, final boolean reusable) {
lock.lock();
try {
Copy link
Member

Choose a reason for hiding this comment

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

@arturobernalg Could you please add this check here?

if (!reusable) {
     entry.discardConnection(CloseMode.GRACEFUL);
}

Copy link
Member Author

Choose a reason for hiding this comment

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

@ok2c done

.min(Comparator.comparingLong(e -> e.getValue().get()))
.map(Map.Entry::getKey)
.map(e -> {
Copy link
Contributor

@yhzdys yhzdys Jul 6, 2025

Choose a reason for hiding this comment

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

@arturobernalg Perhaps this is better?

return entryMap.entrySet().stream()
        .filter(e -> {
            final C conn = e.getKey().getConnection();
            return conn != null && conn.isOpen();
        })
        .min(Comparator.comparingLong(e -> e.getValue().get()))
        .map(e -> {
            e.getValue().incrementAndGet();
            return e.getKey();
        })
        .orElse(null);

Copy link
Member Author

Choose a reason for hiding this comment

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

@yhzdys idd. I just made the change. please check

…t and keeps the entry in the map until the count reaches zero, regardless of whether the connection is still open. The entry is handed back to the parent pool exactly once—on that final release—and any attempt to release an entry that was never leased now raises an IllegalStateException.
@arturobernalg
Copy link
Member Author

@ok2c, it looks like the TestValidateAfterInactivity test is stuck in an infinite loop.

@ok2c
Copy link
Member

ok2c commented Jul 6, 2025

@ok2c, it looks like the TestValidateAfterInactivity test is stuck in an infinite loop.

@arturobernalg It does appear that way. CC @rschmitt

@arturobernalg
Copy link
Member Author

@ok2c, it looks like the TestValidateAfterInactivity test is stuck in an infinite loop.

@arturobernalg It does appear that way. CC @rschmitt

@rschmitt you can find here another example https://github.com/apache/httpcomponents-client/actions/runs/16097757606

@arturobernalg arturobernalg merged commit b1efda3 into apache:master Jul 6, 2025
16 of 17 checks passed
@arturobernalg
Copy link
Member Author

@ok2c cherry pick to 5.5.x ?

@ok2c
Copy link
Member

ok2c commented Jul 6, 2025

@ok2c cherry pick to 5.5.x ?

@arturobernalg Yes, please.

@arturobernalg
Copy link
Member Author

@ok2c cherry pick to 5.5.x ?

@arturobernalg Yes, please.

Done

arturobernalg added a commit that referenced this pull request Jul 6, 2025
…t and keeps the entry in the map until the count reaches zero, regardless of whether the connection is still open. The entry is handed back to the parent pool exactly once—on that final release—and any attempt to release an entry that was never leased now raises an IllegalStateException. (#663)

(cherry picked from commit b1efda3)
@rschmitt
Copy link
Contributor

rschmitt commented Jul 6, 2025

Taking a look, I'll try to get a thread dump

@rschmitt
Copy link
Contributor

rschmitt commented Jul 6, 2025

The fix is trivial, I'll have it out in a second

@rschmitt
Copy link
Contributor

rschmitt commented Jul 6, 2025

#673

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.

4 participants