Skip to content

Fix #12607: DefaultMaven session scope leak on constructor exception - #12629

Open
elharo wants to merge 1 commit into
masterfrom
fix-12607-session-scope-leak
Open

Fix #12607: DefaultMaven session scope leak on constructor exception#12629
elharo wants to merge 1 commit into
masterfrom
fix-12607-session-scope-leak

Conversation

@elharo

@elharo elharo commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Fixes #12607

Problem

In DefaultMaven.doExecute(), sessionScope.enter() was called outside the try-finally block:

sessionScope.enter();
MavenChainedWorkspaceReader chainedWorkspaceReader =
        new MavenChainedWorkspaceReader(request.getWorkspaceReader(), ideWorkspaceReader);
try (CloseableSession closeableSession = ...) {
    ...
} finally {
    sessionScope.exit();
}

If new MavenChainedWorkspaceReader(...) threw (it can throw an NPE if a WorkspaceReader's getRepository() returns null), the sessionScope.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 DefaultMavenSessionScopeTest which:

  1. Creates a mock WorkspaceReader whose getRepository() returns null (triggering NPE in MavenChainedWorkspaceReader)
  2. Calls DefaultMaven.execute() with this bad reader
  3. Verifies the session scope is properly exited (empty internal values list) even though the request failed

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
@elharo
elharo requested a review from Copilot July 30, 2026 12:52

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 MavenChainedWorkspaceReader construction (and newCloseableSession call) inside a new outer try block that guarantees sessionScope.exit() runs in all paths after sessionScope.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 to SessionScope's internal hierarchy/naming, but is acceptable since no public API exists to query scope state.
  • null is passed for the non-nullable superPomProvider constructor parameter — works because the NPE occurs before it's used, but mock(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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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/finally to always call sessionScope.exit().
  • Adds a JUnit test that simulates a failing WorkspaceReader and asserts the SessionScope state 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.

Comment thread impl/maven-core/src/main/java/org/apache/maven/DefaultMaven.java
Comment on lines +78 to +81
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");
Comment on lines +53 to +55
File localRepoDir = Files.createTempDirectory("local-repo").toFile();
localRepoDir.deleteOnExit();
MavenExecutionRequest request = new DefaultMavenExecutionRequest()
Comment on lines +74 to +76
MavenExecutionResult result = defaultMaven.execute(request);

assertFalse(result.getExceptions().isEmpty());
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.

[maven-4.0.x] DefaultMaven: session scope leak on constructor exception

3 participants