This would not really solve the clean / race problem, as module-a could try
to read a dependency after it has been cleaned.
In addition that would break mvn -f module-c/pom.xml because the full
reactor is not loaded and there’s no access to the target die of a module
which is not in the reactor.

Guillaume

Le mer. 5 août 2026 à 17:17, Sergey Chernov <[email protected]> a
écrit :

> > The key detail is that classified/attached artifacts (sources.jar,
> test-jar, javadoc.jar, consumer POMs) are only resolvable from
> project-local-repo during resume. The target/classes fallback in
> ReactorReader only handles plain jars without classifiers. <
>
> Ok, is it an option to create module/target/local-repo-classifier.xml with
> the index of exposed artifacts, create only on successful build, so module
> of the reactor (which is even skipped in "-pl" option) is aware of which
> artifacts it can take from the module target directory. In this case we do
> not need a special rootDir/target/project-local-repo
>
>
> On Wed, Aug 5, 2026 at 5:07 PM Sergey Chernov <[email protected]>
> wrote:
>
> > >I am by no means familiar with this part of Maven, but would it be an
> > option to place "clean" and "install" in separate TaskSegments to avoid
> > the race condition completely?
> >
> > Yes, I was talking about the same. There was a comment regarding it that
> > "compile 4.x+ plugin will compile the code of all modules", but I have
> very
> > strong concerns it's how actually the thing work.
> >
> > "mvn clean install -T4" now executes all phases of clean lifecycle +
> > all phases of install lifecycle (subset of "default" lifecycle) in a list
> > of mojos, in a single foreach loop.
> > Instead, it should run clean lifecycle for all modules, and only then run
> > install lifecycle for all modules.
> >
> > For example, Gradle does it this way and I find this more correct.
> >
> >
> > On Wed, Aug 5, 2026 at 10:49 AM Maarten Mulders <[email protected]>
> > wrote:
> >
> >> Hi Guillaume,
> >>
> >> Your problem statement seems clear to me, but from the three approaches,
> >> it seems to me all three target a consequence of the root cause.
> >> > Since clean and install are placed into the same TaskSegment [...]
> >>
> >> I am by no means familiar with this part of Maven, but would it be an
> >> option to place "clean" and "install" in separate TaskSegments to avoid
> >> the race condition completely? If I understand correctly, it would also
> >> make it practically impossible to "clean" something that was "install"ed
> >> just (the ordering problem when using a lock-based approach).
> >>
> >> Apart from that, I would not be a big fan of a solution that moves the
> >> project-local-repo *outside* the project directory (approach 2).
> >>
> >> Thanks,
> >>
> >> Maarten
> >>
> >> On 03/08/2026 14:09, Guillaume Nodet wrote:
> >> > Hi all,
> >> >
> >> > I'd like to get your input on the fix for GH-12646 — a race condition
> >> with
> >> > project-local-repo during parallel clean install builds.
> >> >
> >> > The problem
> >> >
> >> > When the root pom.xml has a parent that is also part of the reactor
> >> (e.g. a
> >> > super-pom), MultiThreadedBuilder schedules the parent first, then runs
> >> the
> >> > root project and child modules concurrently. Since clean and install
> are
> >> > placed into the same TaskSegment, there is no barrier between them —
> the
> >> > root project's maven-clean-plugin can delete target/ while sibling
> >> modules
> >> > are concurrently writing artifacts into target/project-local-repo,
> >> causing
> >> > the build to fail.
> >> >
> >> > Approaches considered
> >> >
> >> > 1. Lock-based synchronization (ReentrantReadWriteLock in
> ReactorReader)
> >> >
> >> > Acquire a write lock when the project owning target/ enters its clean
> >> > phase, and a read lock when installing artifacts. This prevents the
> >> crash
> >> > (concurrent access) but does not guarantee ordering — a module could
> >> > install artifacts before the root's clean starts, only to have them
> >> wiped.
> >> > It also adds complexity to ReactorReader for what is fundamentally an
> >> > architectural problem.
> >> >
> >> > 2. Move project-local-repo to ~/.m2/ (user home)
> >> >
> >> > E.g. ~/.m2/local-repository/${projectName}_${hash}, similar to how
> >> IntelliJ
> >> > stores project caches. This avoids both the race and the git concern,
> >> but:
> >> > - Hard links (already used by ReactorReader) cannot cross filesystem
> >> > boundaries — if ~/.m2/ is on a different volume, every artifact
> becomes
> >> a
> >> > full copy
> >> > - Stale directories accumulate when projects are deleted/moved, with
> no
> >> > cleanup mechanism
> >> > - CI containers often share ~/.m2/ across builds, causing unwanted
> >> > accumulation
> >> > - Loses project locality (harder to inspect/debug)
> >> >
> >> > 3. Move project-local-repo to .mvn/project-local-repo (chosen)
> >> >
> >> > Move the directory from target/project-local-repo to
> >> > .mvn/project-local-repo. Since maven-clean-plugin only deletes
> target/,
> >> the
> >> > race becomes structurally impossible. ReactorReader fully owns the
> >> > lifecycle — per-GAV cleanup when a project enters its clean phase,
> >> install
> >> > on project success. The existing hard-link optimization continues to
> >> work
> >> > since both directories are on the same filesystem.
> >> >
> >> > The trade-off is that .mvn/project-local-repo needs to be gitignored.
> >> This
> >> > follows the Gradle convention where .gradle/ at the project root is
> >> > universally in .gitignore templates. Maven could also document this
> >> > convention or consider auto-appending the entry.
> >> >
> >> > The fix itself is minimal — the core change is a single line in
> >> > getProjectLocalRepo(), and the rest is removing the lock
> infrastructure
> >> > (net -40 lines).
> >> >
> >> > 4. Keep in target/ but use maven-clean-plugin fast mode
> >> >
> >> > The fast clean option (maven.clean.fast=true, since plugin 3.2)
> >> atomically
> >> > renames target/ instead of recursively deleting it. This would likely
> >> avoid
> >> > the race, but it's opt-in and not the default — users hitting the bug
> >> would
> >> > need to know about it.
> >> >
> >> > FWIW, a PR has been raised on m-clean-p master branch (4.x) to
> refactor
> >> the
> >> > fast cleaner (fixing problems) and make it the default.
> >> >
> >> > Open questions
> >> >
> >> > - Is .mvn/ the right location, or should we consider a different
> >> > project-root directory?
> >> > - Should Maven auto-add .mvn/project-local-repo to .gitignore, or
> >> document
> >> > it as a convention?
> >> > - Are there other considerations I'm missing?
> >> >
> >> > PR: https://github.com/apache/maven/pull/12650
> >> > Issue: https://github.com/apache/maven/issues/12646
> >> >
> >> > Looking forward to your thoughts.
> >> >
> >> >   Cheers
> >> > Guillaume Nodet
> >> >
> >>
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: [email protected]
> >> For additional commands, e-mail: [email protected]
> >>
> >>
>


-- 
------------------------
Guillaume Nodet

Reply via email to