-
Notifications
You must be signed in to change notification settings - Fork 202
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dependencyUpdates task fails with ConcurrentModificationException since 0.52.0 in certain projects #930
Comments
ugh, sorry to hear that @mitchellmebane. I think you're right that it is the same as #907 and simply shifted the problem to now impact you. I believe this is a Gradle bug and that you may need to open an issue with them. The logic of their custom collection is confusing with these lazy side-effects that invalidate the iterator. From what I could tell, that iterator was in their code so any fix would be internal rather than by a plugin, so I'm skeptical that we can give you a proper workaround. |
That's the source of the data. Looks like the actual type of
which probably explains the issue. It might be possible to change |
I was thinking that the realizePending was adding to the collection, which invalidated any existing iterators by incrementing the mod count. This wouldn’t be a threading issue, but that modifications must go through the iterator in typical collections. Java’s concurrent collections use weakly consistent iterators, but non-concurrent throw CME for misuse rather than concurrency. That was my assumption last time I looked, but your rationale is interesting too. At execution time I didn’t expect this to be modified, only at init/configuration build phases. |
Hm, that might be possible. I don't have a good feel for how all the lazy initialization works in Gradle yet.
Right, that would be a reentrancy issue. I guess I tend to conflate them in my mind. The good news is that if it's not caused by multi-threading, I can probably write a deterministic test case, if I can find what behavior is triggering the crash.
Yes, that's definitely what I would expect after reading the Build Lifecycle documentation. I'm going to dig through the other two plugins in my repro project and see if they're modifying the configurations anywhere weird. |
Based on some simple print debugging, it looks like the runtime type of DefaultNamedDomainObjectSet's iterator() implementation is DefaultDomainObjectCollection#iterator, which mostly just delegates to the backing store, which at runtime is FilteredElementSource#iterator. That implementation calls I'll have to set up a real debugger tonight and look more closely. |
It has been a while since I attached a debugger directly to Gradle, but here are my notes. In some cases the tasks accept More generally, for any Java program, you can use a remote attachment. In my projects, before that flag above, I used to use if ("debug" in systemProperties) {
jvmArgs("-Xdebug", "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005")
} IntelliJ may have this built in now and it can all be done directly and understands their kts support. When I first wrote this plugin in groovy on gradle 1.0, IntelliJ had no support and Eclipse's was vastly superior thanks to Spring's plugin. At that time, when print debugging was not enough, I was able to step through this way (I think this was to pinpoint a bug in their repository handler that dropped maven repos by incorrect deduplication). hope this helps. |
IntelliJ is much smarter about this today indeed. I created a separate composite build with my repro project and the plugin project, imported it into IntelliJ, and can set breakpoints in the plugin while starting a debug of the And there is, in fact, a modification of the configurations set during processing. When processing the val lenient = copy.resolvedConfiguration.lenientConfiguration That Here's the call stack when that line is hit: Stack Trace
You can see the execution flows through the I guess I'll have to look at the |
It seems odd that they would add a configuration during dependency resolution? The I know a little about the I would guess that the spring plugin is adding the junit dependency via its BOM, and that triggers pitest to do this crazy logic. |
I am getting a
ConcurrentModificationException
when running thedependencyUpdates
task in some of my Spring Boot projects after upgrading them togradle-versions-plugin
v0.52.0. After some experimentation, I've narrowed it down to projects which use all 3 of these plugins:io.spring.dependency-management
, any version since at least v3.1.0info.solidsoft.pitest
v1.15.0com.github.ben-manes.versions
v0.52.0The relevant bit of the stack trace (I can copy the whole thing here if you'd like):
Crashing line: DependencyUpdates.kt:78
I have a minimal reproducer here: https://github.com/mitchellmebane/gradle-versions-plugin-crash/
This sounds like it might have been caused by the fix to #907, or perhaps that fix just moved the weak point into the loop in
resolveProjects
and changed the timing enough that my projects only hit it now.I don't know much about Gradle internals, but I'll try and dig into this more if I have time.
The text was updated successfully, but these errors were encountered: