Should this ever be allowed?
task blowsUp << { doFirst { println 'ConcurrentModificationException' } }
I basically never use the short-cut form, but in building up some internal
training materials I attempted to do the above essentially to see what would
happen, and wasn't quite expecting the below exception.
The exception logically makes sense as the actions list is indeed being
modified while being iterated over, but it seems that the only way that
should be possible is by nesting doFirst and/or doLast closures. I rather
would have expected gradle to spit out a message something to the effect that
nested doFirst/doLast closure blocks are disallowed.
The other possible option would be to change the internal list structure
explicitly to use a CopyOnWriteArrayList so that changes after iteration has
started would simply not be seen. That would mask issues though, so failing
early seems like a much better option, just ideally with a nicer message to the
user.
Below is the actual exception that occurs using 1.0-milestone-9
java.util.ConcurrentModificationException
at
java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at
org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:56)
at
org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
at
org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:34)
at
org.gradle.api.internal.changedetection.CacheLockHandlingTaskExecuter$1.run(CacheLockHandlingTaskExecuter.java:34)
at
org.gradle.cache.internal.DefaultCacheAccess$2.create(DefaultCacheAccess.java:200)
at
org.gradle.cache.internal.DefaultCacheAccess.longRunningOperation(DefaultCacheAccess.java:172)
at
org.gradle.cache.internal.DefaultCacheAccess.longRunningOperation(DefaultCacheAccess.java:198)
at
org.gradle.cache.internal.DefaultPersistentDirectoryStore.longRunningOperation(DefaultPersistentDirectoryStore.java:111)
at
org.gradle.api.internal.changedetection.DefaultTaskArtifactStateCacheAccess.longRunningOperation(DefaultTaskArtifactStateCacheAccess.java:83)
at
org.gradle.api.internal.changedetection.CacheLockHandlingTaskExecuter.execute(CacheLockHandlingTaskExecuter.java:32)
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:247)
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:61)
at
org.gradle.execution.DefaultBuildExecuter.access$200(DefaultBuildExecuter.java:23)
at
org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:67)
at
org.gradle.api.internal.changedetection.TaskCacheLockHandlingBuildExecuter$1.run(TaskCacheLockHandlingBuildExecuter.java:31)
at
org.gradle.cache.internal.DefaultCacheAccess$1.create(DefaultCacheAccess.java:111)
at
org.gradle.cache.internal.DefaultCacheAccess.useCache(DefaultCacheAccess.java:126)
at
org.gradle.cache.internal.DefaultCacheAccess.useCache(DefaultCacheAccess.java:109)
at
org.gradle.cache.internal.DefaultPersistentDirectoryStore.useCache(DefaultPersistentDirectoryStore.java:103)
at
org.gradle.api.internal.changedetection.DefaultTaskArtifactStateCacheAccess.useCache(DefaultTaskArtifactStateCacheAccess.java:79)
at
org.gradle.api.internal.changedetection.TaskCacheLockHandlingBuildExecuter.execute(TaskCacheLockHandlingBuildExecuter.java:29)
at
org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:61)
at
org.gradle.execution.DefaultBuildExecuter.access$200(DefaultBuildExecuter.java:23)
at
org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:67)
at
org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
at
org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:61)
at
org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:54)
at
org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:155)
at
org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:110)
at
org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:78)
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:302)
at
org.gradle.launcher.cli.CommandLineActionFactory$WithLoggingAction.execute(CommandLineActionFactory.java:286)
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 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
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)
-Spencer