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

Reply via email to