Concurrent Modification Exception during 'gradle tasks'

This problem appears in Gradle 1.0 milestone 6. It appears to come from the Cobertura plugin. I’ve made an effort to identify the origin of the problem, but my build is pretty big and I’m new to Gradle.

========== From my console: ===========

[spina:~/Code/apt/StagingGround] spina% gradle tasks --stacktrace The SourceSet.getClassesDir() method is deprecated and will be removed in the next version of Gradle. You should use the getOutput().getClassesDir() method instead. Disabling CosiMapJUnitTest. Failing because of GC behavior… The SourceSet.getClasses() method is deprecated and will be removed in the next version of Gradle. You should use the getOutput() method instead. :tasks

------------------------------------------------------------ All tasks runnable from root project ------------------------------------------------------------

FAILURE: Build failed with an exception.

  • What went wrong: Execution failed for task ‘:tasks’. Cause: java.util.ConcurrentModificationException (no error message)

  • Try: Run with --info or --debug option to get more log output.

  • Exception is: org.gradle.api.tasks.TaskExecutionException: Execution failed for task ‘:tasks’.

at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:71)

at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:48)

at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:34)

at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:55)

at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:57)

at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:41)

at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:51)

at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:52)

at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:42)

at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:243)

at org.gradle.execution.DefaultTaskGraphExecuter.executeTask(DefaultTaskGraphExecuter.java:192)

at org.gradle.execution.DefaultTaskGraphExecuter.doExecute(DefaultTaskGraphExecuter.java:177)

at org.gradle.execution.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:83)

at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:36)

at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:70)

at org.gradle.execution.DefaultBuildExecuter.access$300(DefaultBuildExecuter.java:23)

at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:80)

at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)

at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:70)

at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:63)

at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:157)

at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:112)

at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:80)

at org.gradle.launcher.cli.RunBuildAction.execute(RunBuildAction.java:42)

at org.gradle.launcher.cli.RunBuildAction.execute(RunBuildAction.java:28)

at org.gradle.launcher.exec.ExceptionReportingAction.execute(ExceptionReportingAction.java:32)

at org.gradle.launcher.exec.ExceptionReportingAction.execute(ExceptionReportingAction.java:21)

at org.gradle.launcher.cli.CommandLineActionFactory$WithLoggingAction.execute(CommandLineActionFactory.java:233)

at org.gradle.launcher.cli.CommandLineActionFactory$WithLoggingAction.execute(CommandLineActionFactory.java:217)

at org.gradle.launcher.Main.doAction(Main.java:48)

at org.gradle.launcher.exec.EntryPoint$1.execute(EntryPoint.java:53)

at org.gradle.launcher.exec.EntryPoint$1.execute(EntryPoint.java:51)

at org.gradle.launcher.exec.Execution.execute(Execution.java:28)

at org.gradle.launcher.exec.EntryPoint.run(EntryPoint.java:39)

at org.gradle.launcher.Main.main(Main.java:39)

at org.gradle.launcher.ProcessBootstrap.runNoExit(ProcessBootstrap.java:51)

at org.gradle.launcher.ProcessBootstrap.run(ProcessBootstrap.java:33)

at org.gradle.launcher.GradleMain.main(GradleMain.java:24) Caused by: java.util.ConcurrentModificationException

at org.gradle.api.internal.DefaultDomainObjectCollection$IteratorImpl.next(DefaultDomainObjectCollection.java:313)

at org.gradle.api.internal.GraphAggregator.group(GraphAggregator.java:33)

at org.gradle.api.tasks.diagnostics.internal.SingleProjectTaskReportModel.build(SingleProjectTaskReportModel.java:61)

at org.gradle.api.tasks.diagnostics.TaskReportTask.generate(TaskReportTask.java:67)

at org.gradle.api.tasks.diagnostics.AbstractReportTask.generate(AbstractReportTask.java:67)

at org.gradle.api.internal.BeanDynamicObject.invokeMethod(BeanDynamicObject.java:158)

at org.gradle.api.internal.CompositeDynamicObject.invokeMethod(CompositeDynamicObject.java:93)

at org.gradle.api.tasks.diagnostics.TaskReportTask_Decorated.invokeMethod(Unknown Source)

at org.gradle.util.ReflectionUtil.invoke(ReflectionUtil.groovy:23)

at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$2.execute(AnnotationProcessingTaskFactory.java:129)

at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$2.execute(AnnotationProcessingTaskFactory.java:127)

at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:63)

… 37 more

================ END CONSOLE OUTPUT =================

This is my build file:

==== begin build.gradle ====

// The sonar plugin collects build metrics. Useful for quality assurance. apply plugin: “sonar”

sonar {

project {

// TODO once using gradle v 1.0 milestone 7, the dynamicAnalysis line won’t be needed.

dynamicAnalysis = “reuseReports”

sourceEncoding = “UTF-8”

} }

// This allows all groovy projects to easily reference the same groovy jar for building. groovy_jar = “…/Libraries/groovy-all-1.7.3.jar”

//ant.importBuild ‘build.xml’ dependsOnChildren()

allprojects {

repositories {

mavenCentral()

} }

subprojects {

// The cobertura plugin doesn’t come with gradle by default. This makes it available and applies it.

buildscript {

// using a variable to make wiki look cleaner

def githubBase = ‘https://github.com/valkolovos/gradle_cobertura/raw/master/ivy

apply from: “${githubBase}/gradle_cobertura/gradle_cobertura/1.0-rc4/coberturainit.gradle”

}

sonar {

project {

coberturaReportPath = file("$reportsDir/cobertura/coverage.xml") //

testReportPath = file("$reportsDir/tests/junitreports")

dynamicAnalysis = “reuseReports”

}

}

apply plugin:‘java’

sourceCompatibility = 6

dependencies {

testCompile ‘junit:junit:4.4’

}

test {

// Make sure that tests are executed from the APT root. This make relative path lookup work.

workingDir = new File(project.projectDir.getCanonicalPath() + “/…/”)

// TODO this is temporary so we can skip tagged tests.

systemProperties “apt.build.is.gradle”: “true”

systemProperties “stsci.skip.performance”: “true”

// TODO this should be toggled dynamically.

systemProperties “stsci.skip.network.tests”: “true”

}

compileJava {

// This makes it so that the class filed don’t have debug information.

// This is how our ant build used to work.

options.debug = false

}

// The ant build puts Manifests into the jar by importing a file.

// It’s not a very Gradle-y way of doing things, but works for now

// Eventually it would be desirable to make these files in the build itself.

jar {

manifest {

// Not actually made by ANT— just a cheap way to reduce differences.

attributes(“Ant-Version”: “Apache Ant 1.8.2”, “Created-By”: “1.6.0_29-b11-402-10M3527 (Apple Inc.)”)

def manifestLocation = “${project.name}/MANIFEST.MF”

if(new File(manifestLocation).exists()) {

logger.info(project.name + “.jar will have a MANIFEST copied from MANIFEST.MF in it’s root dir.”)

from(‘MANIFEST.MF’)

} else {

logger.info(project.name + " doesn’t have a MANIFEST.MF in it’s root dir.")

}

}

}

} ====end build.gradle====

If I comment out the following lines then ‘gradle tasks’ works again:

buildscript {

// using a variable to make wiki look cleaner

def githubBase = ‘https://github.com/valkolovos/gradle_cobertura/raw/master/ivy

apply from: “${githubBase}/gradle_cobertura/gradle_cobertura/1.0-rc4/coberturainit.gradle”

}

coberturaReportPath = file("$reportsDir/cobertura/coverage.xml")

I’m not sure how those lines are breaking my build.

Note to self, the problem entered my build during the following changeset (found using bisect):

The first bad revision is: changeset:

13615:e28b6e3c2872 parent:

13609:2946d90d6cbc user:

spina date:

Thu Dec 22 17:09:16 2011 -0500 summary:

PR 69384 - Gradle now runs Tina Tests (though some are skipped). Hooked up Cobertura (code coverage) and Sonar.

I got a similar exception when trying to upgrade from milestone-3 to a milestone-7 snapshot. I’m also using the cobertura plugin and will try and see if that is the culprit for me aswell. (i did manage to build my projects but the tasks task bugs out).

I’ve raised an issue in our tracker for this. We’ll hopefully get to it soon.

Thanks for putting in the diagnostic work.

Hi guys,

I have attached a simple build script that reproduces this issue in GRADLE-2023. In my build, this problem surfaced when I added task dependencies configured via a closure that triggers a task rule. In case there is only one such dynamic dependency there is no problem - probably because the according task is resolved at the end of the iteration and the concurrent modification exception goes undetected by the iterator. Also, I observed this issue only when the dynamic tasks are created on a subproject, but not when created on the root project. Here is a sample script that should reproduce the problem - it must be called on a subproject of the root project:

Rule rule = [
    getDescription: { "Rule that creates 'dynamicTask' task." },
    apply: { String taskName ->
        if (taskName.startsWith('dynamicTask')) {
            project.tasks.add(taskName)
        }
    },
      toString: { getDescription() }
] as Rule
  project.tasks.addRule rule
  project.tasks.add('someTask') {
    dependsOn { project.tasks.findByName('dynamicTask1') }
}
  project.tasks.add('anotherTask') {
    dependsOn { project.tasks.findByName('dynamicTask2') }
}

Regards,

Detelin

I have hit this issue creating dynamic tasks in a plugin. The dynamic tasks have dependencies on existing java tasks. The plugin is applied to certain sub-tasks. Interesting is that running ‘gradle tasks’ fails in the parent project but works in the sub-task where the plugin is applied. Its also a bit random. There is obviously some sequence of events that causes it work sometimes but most times it fails. I don’t use the CoberturaPlugin explicitly anywhere

i’ve isolated the line that causes the java.util.ConcurrentModificationException: project.getAt(PLUGIN_EXTENSION_NAME).wsdlDescriptors.each { k,v ->

// lots of other code …

project.tasks.add(name: “wsdl2Java${k.capitalize()}”,type: JavaExec) {

description=“Generates Java source for wsdl:${k}=${v.file}”

outputs.upToDateSpec = new org.gradle.api.specs.AndSpec()

outputs.files generatedWsdlDir

inputs.files project.configurations.compile, wsdlFile

main = mc

classpath = cp

args = ag

}

project.clean.dependsOn “cleanWsdl2Java${k.capitalize()}” //This is the line that causes the java.util.ConcurrentModificationException

project.“compile${wsdlSrcSetName.capitalize()}Java”.dependsOn “wsdl2Java${k.capitalize()}”

// This line works } project.compileJava.dependsOn project."${wsdlSrcSetName}Classes"

//This line works …

I’ve resolved my error by creating a single cleanWsdl task and creating the clean.dependsOn cleanWsdl. The dynamic patter clean would have all executed the same thing so were redundant when I had more than 1 wsdl anyway. If I had designed it differently with a sourceSet for each wsdl then maybe it would have still occurred but that would be overkill for my purposes.

This happens on milestone-9 build. I cannot say what the rootcause, but figured out the case this error happens with gradle cobertura plugin. Maybe gradle gurus can shed some light.

Please Refer: https://github.com/valkolovos/gradle_cobertura/issues/18

I just posted a small patch to GRADLE-2023 that seems to fix it for me. I’m not very familiar with the Gradle code base so it’s probably not the greatest ‘fix’.