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
