Release the connection for each redirect hop in parse(URL) - #113
Merged
Conversation
SchemaTypeLoaderBase.parse(URL) follows up to five redirects. Each pass opens a connection and calls getResponseCode(), which reads the response, then moves on to the next URL without touching that connection again. Only the final one is closed, by the try-with-resources around getInputStream(). The redirect bodies are never read, so the sockets sit in the keep-alive cache holding a descriptor until a finalizer or the cache timeout reclaims them. Call disconnect() on the hop being abandoned instead. Added ParseUrlRedirectTest, a loopback HttpServer serving a three-hop redirect chain, to pin the follow behaviour - it passes either way and guards against disconnect() breaking the chain. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
pjfanning
added a commit
that referenced
this pull request
Sep 7, 2026
) ParseUrlRedirectTest (added in #113) starts a com.sun.net.httpserver server on loopback to pin redirect following. That package is not in the Android API signature animalsniffer checks against, so animalsnifferTest reports 19 undefined references and ./gradlew check fails. The signature describes what the published artifact may use. Test code never ships and never runs on Android, so exclude just this file rather than weaken the signature for main. Excluding the whole test source set would also work - the animalsniffer block already carries a commented-out "sourceSets = [sourceSets.main]" for that - but this keeps the rest of the tests covered. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
SchemaTypeLoaderBase.parse(URL)follows up to five redirects. Each pass through the loop opens a connection and callsgetResponseCode()— which sends the request and reads the response — then reassignsurland loops, never touching that connection again. Only the final connection is closed, by the try-with-resources aroundconn.getInputStream().The redirect bodies are never read, so those sockets sit in the keep-alive cache holding a file descriptor until a finalizer or the cache timeout reclaims them. Fetching a redirected schema can therefore hold five idle sockets per call.
This calls
disconnect()on the hop being abandoned.Added
ParseUrlRedirectTest: a loopbackHttpServerserving a three-hop redirect chain to a small document. It passes both with and without the fix — its job is to pin the redirect-following behaviour and provedisconnect()does not break the chain, since the descriptor release itself is not directly observable from a test.🤖 Generated with Claude Code