Fix #12646: project-local-repo clean race condition when root pom has parent - #12650
Draft
gnodet wants to merge 2 commits into
Draft
Fix #12646: project-local-repo clean race condition when root pom has parent#12650gnodet wants to merge 2 commits into
gnodet wants to merge 2 commits into
Conversation
… parent When the root pom.xml has a parent (super-pom) in the reactor, MultiThreadedBuilder schedules the super-pom first, then builds the root pom and sibling modules in parallel. The root pom's clean phase (maven-clean-plugin) deletes the entire target/ directory, which includes project-local-repo. Concurrently, sibling modules that complete successfully write artifacts into target/project-local-repo via ReactorReader.installIntoProjectLocalRepository(). This race causes maven-clean-plugin to fail because the directory is being written to while it tries to delete it. Fix: Add a ReentrantReadWriteLock to ReactorReader that coordinates access to the project-local-repo directory between clean and install operations. When the project whose build directory contains the project-local-repo enters its clean phase, a write lock is acquired to block concurrent installs. The write lock is released when the clean mojo completes (succeeds or fails). Install operations acquire a read lock, allowing multiple concurrent installs but blocking while the owning project's clean is running. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e clean race Move the project-local-repo directory from target/project-local-repo to .mvn/project-local-repo so it is not affected by maven-clean-plugin's deletion of target/. This eliminates the race condition in parallel builds where maven-clean-plugin deletes target/ while sibling modules concurrently write artifacts into project-local-repo. The previous lock-based approach prevented crashes but could not guarantee ordering between clean and install operations. Moving the directory outside target/ makes the race structurally impossible — ReactorReader fully owns the lifecycle of project-local-repo (per-GAV cleanup on clean, install on project success). Co-Authored-By: Claude Opus 4.6 <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.
Summary
Move
project-local-repofromtarget/project-local-repoto.mvn/project-local-reposo it is not affected bymaven-clean-plugin's deletion oftarget/.This eliminates the race condition in parallel builds (
mvn clean install -T N) where the root project'smaven-clean-plugindeletestarget/while sibling modules concurrently write artifacts intotarget/project-local-repo.Root cause
In Maven 4,
cleanandinstallphases are placed into the sameTaskSegment, so they execute concurrently across projects in parallel builds. When the rootpom.xmlhas a parent (e.g. a super-pom in the reactor),MultiThreadedBuilderschedules the parent first, then runs the root project and child modules in parallel. The root project's clean phase (viamaven-clean-plugin) races with sibling modules installing artifacts intotarget/project-local-repo.Fix
Move
project-local-repofromtarget/to.mvn/, making it structurally impossible formaven-clean-pluginto interfere.ReactorReaderfully owns the lifecycle:ProjectSucceeded, artifacts are hard-linked (or copied) into.mvn/project-local-repoThis approach is simpler than the previous lock-based fix — the
ReentrantReadWriteLockandisProjectLocalRepoOwner()are removed entirely.Precedent
Storing build-related data outside
target/(survivingclean) is established:~/.m2/.cache/maven-build-cache.gradle/directory at project root (universally gitignored)Trade-off
.mvn/project-local-reposhould be added to.gitignore— similar to how Gradle projects gitignore.gradle/.Fixes #12646
🤖 Generated with Claude Code