Skip to content

Conversation

@ash211
Copy link
Contributor

@ash211 ash211 commented Oct 6, 2022

Addresses #2413

Before this PR

java.util.ConcurrentModificationException thrown from this plugin:

Caused by: java.util.ConcurrentModificationException
        at org.gradle.api.internal.collections.FilteredCollection$FilteringIterator.findNext(FilteredCollection.java:121)
        at org.gradle.api.internal.collections.FilteredCollection$FilteringIterator.next(FilteredCollection.java:140)
        at org.gradle.api.internal.DefaultDomainObjectCollection$IteratorImpl.next(DefaultDomainObjectCollection.java:485)
        at com.palantir.baseline.plugins.BaselineNullAway.lambda$anyProjectUsesJava15$4(BaselineNullAway.java:138)
        at com.palantir.baseline.plugins.BaselineNullAway.anyProjectUsesJava15(BaselineNullAway.java:137)
        at com.palantir.baseline.plugins.BaselineNullAway$5.lambda$execute$0(BaselineNullAway.java:128)

After this PR

==COMMIT_MSG==
Fix ConcurrentModificationExceptions thrown from BaselineNullAway
==COMMIT_MSG==

Possible downsides?

I think this exception indicates that the project's task list is being modified/resolved at the same time as we iterate over it in this class.

By making a copy before iterating, I think we'll reduce the CMEs being thrown, but not actually fix the underlying issue of concurrent changes happening. I'm not super familiar with Gradle internals, but think we may instead need to do something where BaselineNullAway runs in a doLast so it doesn't interfere with project resolution.

This fix was confirmed on an internal failing repro, but we don't have a test case for it as part of this PR.

By using the TaskCollection's .anyMatch() directly, we hope that it is a bit smarter about modification during iteration versus converting to a Stream and using Stream#anyMatch().

@changelog-app
Copy link

changelog-app bot commented Oct 6, 2022

Generate changelog in changelog/@unreleased

Type

  • Feature
  • Improvement
  • Fix
  • Break
  • Deprecation
  • Manual task
  • Migration

Description

Fix ConcurrentModificationExceptions thrown from BaselineNullAway

Check the box to generate changelog(s)

  • Generate changelog entry

@ash211 ash211 marked this pull request as ready for review October 6, 2022 05:49
@ash211 ash211 requested a review from carterkozak October 6, 2022 05:49
private static boolean anyProjectUsesJava15(Project proj) {
return proj.getAllprojects().stream()
.anyMatch(project -> project.getTasks().withType(JavaCompile.class).stream()
.anyMatch(project -> ImmutableList.copyOf(project.getTasks().withType(JavaCompile.class)).stream()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we would be better off replacing the Collection.stream() here using something along these lines:

project.getTasks().withType(JavaCompile.class).matching(comp -> {
  JavaVersion javaVersion = JavaVersion.toVersion(comp.getTargetCompatibility());
  return javaVersion == JavaVersion.VERSION_15;
}).isEmpty()

I suspect the TaskContainer may be a bit smarter about modification within iteration when it controls the iteration rather than returning a stream wrapping a spliterator, but it's difficult to say without a reliable reproducer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this by testing gw classes --stacktrace on my internal failing repo, and that command:

  • fails on com.palantir.baseline:gradle-baseline-java:4.180.0
  • succeeds on com.palantir.baseline:gradle-baseline-java:4.180.0-8-ga477298
  • fails on com.palantir.baseline:gradle-baseline-java:4.180.0-9-g05114a5

So I think the ImmutableList copy approach works and the TaskCollection one doesn't. At least it gets these runs to pass.

@ash211 ash211 changed the title Collect JavaCompile tasks to a List before iterating over it Fix ConcurrentModificationExceptions thrown from BaselineNullAway Oct 7, 2022
@ash211 ash211 force-pushed the aash/attempt-cme-fix branch from 05114a5 to a477298 Compare October 7, 2022 19:31
@ash211 ash211 requested a review from carterkozak October 7, 2022 19:32
Copy link
Contributor

@carterkozak carterkozak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@bulldozer-bot bulldozer-bot bot merged commit df1489b into develop Oct 7, 2022
@bulldozer-bot bulldozer-bot bot deleted the aash/attempt-cme-fix branch October 7, 2022 19:50
@svc-autorelease
Copy link
Collaborator

Released 4.181.0

This was referenced Oct 7, 2022
bulldozer-bot bot pushed a commit to palantir/witchcraft-api that referenced this pull request Oct 8, 2022
###### _excavator_ is a bot for automating changes across repositories.

Changes produced by the roomba/latest-baseline-oss check.

# Release Notes
## 4.181.0
| Type | Description | Link |
| ---- | ----------- | ---- |
| Fix | Fix ConcurrentModificationExceptions thrown from BaselineNullAway | palantir/gradle-baseline#2427 |



To enable or disable this check, please contact the maintainers of Excavator.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants