Fix #12607: DefaultMaven session scope leak on constructor exception - #12629
Fix #12607: DefaultMaven session scope leak on constructor exception#12629elharo wants to merge 1 commit into
Conversation
Wrap sessionScope.enter() in a try-finally block so that sessionScope.exit() is always called, even when the MavenChainedWorkspaceReader constructor throws. Previously, sessionScope.enter() was called outside the try-finally block. If the intervening constructor threw, sessionScope.exit() was never executed, leaking the session scope's thread-local state. Fixes gh-12607
gnodet
left a comment
There was a problem hiding this comment.
LGTM ✅
Correct and minimal fix for a real session scope thread-local leak when MavenChainedWorkspaceReader construction fails between enter() and the try block. The test validates the exact failure scenario.
Details:
- The production code change moves the
MavenChainedWorkspaceReaderconstruction (andnewCloseableSessioncall) inside a new outer try block that guaranteessessionScope.exit()runs in all paths aftersessionScope.enter(). The normal execution path is unchanged; only the error path is fixed.
Minor observations (non-blocking):
- The test verifies scope cleanup via reflection on a parent class field (
getSuperclass().getDeclaredField("values")). This couples the test toSessionScope's internal hierarchy/naming, but is acceptable since no public API exists to query scope state. nullis passed for the non-nullablesuperPomProviderconstructor parameter — works because the NPE occurs before it's used, butmock(SuperPomProvider.class)would be slightly more robust.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of gnodet
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Fixes a session-scope leak in DefaultMaven.doExecute() when MavenChainedWorkspaceReader construction throws, and adds a regression test to ensure SessionScope.exit() always runs.
Changes:
- Wraps workspace-reader construction and session creation in an outer
try/finallyto always callsessionScope.exit(). - Adds a JUnit test that simulates a failing
WorkspaceReaderand asserts theSessionScopestate is cleaned up.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| impl/maven-core/src/main/java/org/apache/maven/DefaultMaven.java | Ensures sessionScope.exit() executes even if workspace reader construction fails. |
| impl/maven-core/src/test/java/org/apache/maven/DefaultMavenSessionScopeTest.java | Adds regression coverage for session-scope cleanup on workspace-reader errors. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Field valuesField = SessionScope.class.getSuperclass().getDeclaredField("values"); | ||
| valuesField.setAccessible(true); | ||
| List<?> values = (List<?>) valuesField.get(sessionScope); | ||
| assertTrue(values.isEmpty(), "Session scope must be exited even on workspace reader error"); |
| File localRepoDir = Files.createTempDirectory("local-repo").toFile(); | ||
| localRepoDir.deleteOnExit(); | ||
| MavenExecutionRequest request = new DefaultMavenExecutionRequest() |
| MavenExecutionResult result = defaultMaven.execute(request); | ||
|
|
||
| assertFalse(result.getExceptions().isEmpty()); |
Fixes #12607
Problem
In
DefaultMaven.doExecute(),sessionScope.enter()was called outside the try-finally block:If
new MavenChainedWorkspaceReader(...)threw (it can throw an NPE if aWorkspaceReader'sgetRepository()returnsnull), thesessionScope.exit()in the finally block would never execute. This leaked the session scope's thread-local state.Fix
Wrapped subsequent code in an outer try-finally, ensuring
sessionScope.exit()is always called regardless of where the exception occurs.Testing
Added
DefaultMavenSessionScopeTestwhich:WorkspaceReaderwhosegetRepository()returnsnull(triggering NPE inMavenChainedWorkspaceReader)DefaultMaven.execute()with this bad reader