Repository navigation
[Backport maven-3.10.x] Fix thread-safety in DefaultModelValidator (fix #11618) - #13596
arturobernalg wants to merge 1 commit into
Conversation
gnodet-bot
left a comment
There was a problem hiding this comment.
Clean backport. The two-line production change is exactly right: ConcurrentHashMap.newKeySet() fixes the thread-safety race, and the id != null guard is a required companion because ConcurrentHashMap.contains(null) throws NullPointerException (unlike HashSet). Without it, a missing groupId or artifactId would NPE at the cache lookup before reaching the null-handling in validateStringNotEmpty.
One note on the concurrency test: the test parameters (10 threads × 100 iterations) are too small to reliably trigger the HashMap tree-restructuring race that causes the original ClassCastException. I confirmed this locally — the test passes identically with the pre-fix HashSet. This is an inherent limitation of deterministic concurrency tests; the race requires specific thread interleaving during resize. The test still has value as a smoke test (no deadlock, no unexpected exceptions), but it cannot dynamically validate the fix. Consider bumping to at least 50 threads × 1000 iterations to meaningfully increase the probability of catching a future regression.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
DefaultModelValidator is a singleton, but its validIds field was a plain HashSet that could be mutated by several threads during model validation, for instance with the breadth-first dependency collector. A concurrent HashMap restructuring could then make a reader fail with a ClassCastException. The field is now a concurrent set, as in the Maven 4 maven-impl module, and a null id is no longer looked up in it. Backport of apache#11734 to maven-3.10.x.
1670725 to
96c661f
Compare
|
Raised the test to 50 threads and 1000 iterations in 96c661f, as suggested. I checked it against the old |
|
@arturobernalg you aware of #13303 ? |
|
@arturobernalg merged "by age", but thanks! |
Backport of #11734 to maven-3.10.x.
DefaultModelValidatoris a singleton, but itsvalidIdsfield is a plainHashSeton this branch, which several threads can mutate during model validation, for instance with the breadth-first dependency collector. A concurrent restructuring of theHashMapbehind it can make a reader fail with aClassCastException(#11618). The field is nowConcurrentHashMap.newKeySet(), as on master and on maven-4.0.x, and anullid is no longer looked up in it.The main change applied after adapting the module path. The test
testConcurrentValidationwas added by hand to the existing test class. It is a regression guard, and like the original it does not fail reliably without the change, because the race is timing dependent.maven-model-builderand its dependencies pass (207 tests) and spotless is clean. I did not run the integration tests.To make clear that you license your contribution under
the Apache License Version 2.0, January 2004
check one of the following: