[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: | finalizedByBug.gradle | ||||||||
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 file. |
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 file. |
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 I look into this problem when I have some spare cycles. In meantime, we would love a PR from you |
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. |