[GRADLE-2957] finalizedBy may cause IndexOutOfBundsException Created: 19/Nov/13 Updated: 03/Oct/14 Resolved: 03/Oct/14 |
|
| Status: | Resolved |
| Project: | Gradle |
| Affects Version/s: | None |
| Fix Version/s: | 2.2-rc-1 |
| Type: | Bug | ||
| Reporter: | Szczepan Faber | Assignee: | Marcin Erdmann |
| Resolution: | Fixed | Votes: | 2 |
| Attachments: |
|
||||||||
| Issue Links: |
|
||||||||
| Description |
|
Some legal combination of finalizedBy and dependsOn may cause following exception: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.onOrderingCycle(DefaultTaskExecutionPlan.java:255) at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.determineExecutionPlan(DefaultTaskExecutionPlan.java:211) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.ensurePopulated(DefaultTaskGraphExecuter.java:148) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:82) at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.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:166) at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:113) at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:81) at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:64) at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:33) at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:24) at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:35) at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:45) at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:34) at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:125) at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:42) at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:125) at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:24) at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:125) at org.gradle.launcher.daemon.server.exec.StartStopIfBuildAndStop.execute(StartStopIfBuildAndStop.java:33) at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:125) at org.gradle.launcher.daemon.server.exec.ReturnResult.execute(ReturnResult.java:34) at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:125) at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:71) at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:69) at org.gradle.util.Swapper.swap(Swapper.java:38) at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:69) at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:125) at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:60) at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:34) at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:125) at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:60) at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:34) at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:125) at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:45) at org.gradle.launcher.daemon.server.DaemonStateCoordinator.runCommand(DaemonStateCoordinator.java:186) at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy.doBuild(StartBuildOrRespondWithBusy.java:49) at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:34) at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:125) at org.gradle.launcher.daemon.server.exec.HandleStop.execute(HandleStop.java:36) at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:125) at org.gradle.launcher.daemon.server.exec.DaemonHygieneAction.execute(DaemonHygieneAction.java:36) at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:125) at org.gradle.launcher.daemon.server.exec.CatchAndForwardDaemonFailure.execute(CatchAndForwardDaemonFailure.java:32) at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:125) at org.gradle.launcher.daemon.server.exec.DefaultDaemonCommandExecuter.executeCommand(DefaultDaemonCommandExecuter.java:51) at org.gradle.launcher.daemon.server.DefaultIncomingConnectionHandler$ConnectionWorker.handleCommand(DefaultIncomingConnectionHandler.java:155) at org.gradle.launcher.daemon.server.DefaultIncomingConnectionHandler$ConnectionWorker.receiveAndHandleCommand(DefaultIncomingConnectionHandler.java:128) at org.gradle.launcher.daemon.server.DefaultIncomingConnectionHandler$ConnectionWorker.run(DefaultIncomingConnectionHandler.java:116) at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:66) I can repro this but it's really tangled and I don't have a small repro sample to attach. |
| Comments |
| Comment by Daniel C. Greene [ 18/Mar/14 ] |
|
I'm able to reproduce this issue with the attached gradle file. |
| Comment by Damien Coraboeuf [ 17/Sep/14 ] |
|
I have this very same issue with Gradle 1.12. After some investigation, the error seems located in https://github.com/gradle/gradle/blob/RB_1.12/subprojects/core/src/main/groovy/org/gradle/execution/taskgraph/DefaultTaskExecutionPlan.java, line 335: final List<TaskInfo> firstCycle = new ArrayList<TaskInfo>(graphWalker.findCycles().get(0)); The graphWalker.findCycles() returns an empty collection. |
| Comment by Szczepan Faber [ 17/Sep/14 ] |
|
Can you try Gradle 2.0? I could swear I fixed this issue (though I don't remember why the ticket was not closed). |
| Comment by Damien Coraboeuf [ 18/Sep/14 ] |
|
I'll try with Gradle 2.0 and 2.1, with the attached finalizedByBug.gradle |
| Comment by Damien Coraboeuf [ 18/Sep/14 ] |
|
Same error with Gradle 2.0: ./gradlew --version -b finalizedByBug.gradle ------------------------------------------------------------ Gradle 2.0 ------------------------------------------------------------ Build time: 2014-07-01 07:45:34 UTC Build number: none Revision: b6ead6fa452dfdadec484059191eb641d817226c Groovy: 2.3.3 Ant: Apache Ant(TM) version 1.9.3 compiled on December 23 2013 JVM: 1.8.0_05 (Oracle Corporation 25.5-b02) OS: Mac OS X 10.9.3 x86_64 ./gradlew -b finalizedByBug.gradle --stacktrace FAILURE: Build failed with an exception. * What went wrong: Index: 0, Size: 0 * Try: Run with --info or --debug option to get more log output. * Exception is: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.onOrderingCycle(DefaultTaskExecutionPlan.java:335) at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.determineExecutionPlan(DefaultTaskExecutionPlan.java:231) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.ensurePopulated(DefaultTaskGraphExecuter.java:148) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:82) |
| Comment by Damien Coraboeuf [ 18/Sep/14 ] |
|
Same error with Gradle 2.1: ./gradlew --version -b finalizedByBug.gradle ------------------------------------------------------------ Gradle 2.1 ------------------------------------------------------------ Build time: 2014-09-08 10:40:39 UTC Build number: none Revision: e6cf70745ac11fa943e19294d19a2c527a669a53 Groovy: 2.3.6 Ant: Apache Ant(TM) version 1.9.3 compiled on December 23 2013 JVM: 1.8.0_05 (Oracle Corporation 25.5-b02) OS: Mac OS X 10.9.3 x86_64 ./gradlew -b finalizedByBug.gradle --stacktrace FAILURE: Build failed with an exception. * What went wrong: Index: 0, Size: 0 * Try: Run with --info or --debug option to get more log output. * Exception is: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.onOrderingCycle(DefaultTaskExecutionPlan.java:342) at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.determineExecutionPlan(DefaultTaskExecutionPlan.java:238) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.ensurePopulated(DefaultTaskGraphExecuter.java:150) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:84) at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:29) |
| Comment by Damien Coraboeuf [ 18/Sep/14 ] |
|
Again, I've had this error with our real big project but this can be easily reproduced using the attached finalizedByBug.gradle |
| Comment by Szczepan Faber [ 18/Sep/14 ] |
|
Thanks a lot for investigation! |
| Comment by Damien Coraboeuf [ 18/Sep/14 ] |
|
The following test in DefaultTaskExecutionPlanTest allows to reproduce the problem:
@Issue("GRADLE-2957")
def "dependent tasks with the same finalizer"() {
// Finalizer task
Task finalTask = task('finalTask')
// Task with this finalizer
Task taskOne = task('taskOne', finalizedBy: [finalTask])
Task taskTwo = task('taskTwo', finalizedBy: [finalTask])
// Task to call, with the same finalizer than one of its dependencies
Task buggyTask = task('buggyTask', dependsOn: [taskOne], finalizedBy: [taskTwo])
when:
addToGraphAndPopulate([buggyTask])
then:
executes(taskOne, buggyTask, taskTwo, finalTask)
}
|
| Comment by Damien Coraboeuf [ 18/Sep/14 ] |
|
When debugging the test, I saw that taskTwo and taskOne were considered must successors to the finalTask. It looks a bit strange to me. Any idea? It seems to me that this should be the other way round, that a finalizer should be considered a successor of the finalized task in the graph, and not the other way round. |
| Comment by Szczepan Faber [ 18/Sep/14 ] |
|
Nice debugging! You seem to be close to get it fixed |
| Comment by Damien Coraboeuf [ 18/Sep/14 ] |
|
Coming soon... |
| Comment by Damien Coraboeuf [ 18/Sep/14 ] |
|
PR at https://github.com/gradle/gradle/pull/333 I was able:
Damien. |
| Comment by Szczepan Faber [ 18/Sep/14 ] |
|
Thanks so much! We'll look into the PR. |