Maven
  1. Maven
  2. MNG-3221

Infinite loop in DefaultLifecycleExecutor

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0.7
    • Fix Version/s: 2.0.9
    • Component/s: Plugins and Lifecycle
    • Labels:
      None
    • Patch Submitted:
      Yes
    • Number of attachments :
      3

      Description

      Defining this following report:

      MyReport.java
      /**
       * @goal mygoal
       * @execute phase="site"
       */
      public class MyReport
          extends AbstractMavenReport{}
      

      I got this following loop:

      	DefaultLifecycleExecutor.forkProjectLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 896	
      	DefaultLifecycleExecutor.forkLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 739	
      	DefaultLifecycleExecutor.executeGoals(List, Stack, MavenSession, MavenProject) line: 530	
      	DefaultLifecycleExecutor.executeGoalWithLifecycle(String, Stack, MavenSession, Map, MavenProject, Lifecycle) line: 480	
      	DefaultLifecycleExecutor.forkProjectLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 896	
      	DefaultLifecycleExecutor.forkLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 739	
      	DefaultLifecycleExecutor.executeGoals(List, Stack, MavenSession, MavenProject) line: 530	
      	DefaultLifecycleExecutor.executeGoalWithLifecycle(String, Stack, MavenSession, Map, MavenProject, Lifecycle) line: 480	
      	DefaultLifecycleExecutor.forkProjectLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 896	
      	DefaultLifecycleExecutor.forkLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 739	
      	DefaultLifecycleExecutor.executeGoals(List, Stack, MavenSession, MavenProject) line: 530	
      	DefaultLifecycleExecutor.executeGoalWithLifecycle(String, Stack, MavenSession, Map, MavenProject, Lifecycle) line: 480	
      	DefaultLifecycleExecutor.forkProjectLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 896	
      	DefaultLifecycleExecutor.forkLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 739	
      	DefaultLifecycleExecutor.executeGoals(List, Stack, MavenSession, MavenProject) line: 530	
      	DefaultLifecycleExecutor.executeGoalWithLifecycle(String, Stack, MavenSession, Map, MavenProject, Lifecycle) line: 480	
      	DefaultLifecycleExecutor.forkProjectLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 896	
      	DefaultLifecycleExecutor.forkLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 739	
      	DefaultLifecycleExecutor.executeGoals(List, Stack, MavenSession, MavenProject) line: 530	
      	DefaultLifecycleExecutor.executeGoalWithLifecycle(String, Stack, MavenSession, Map, MavenProject, Lifecycle) line: 480	
      	DefaultLifecycleExecutor.forkProjectLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 896	
      	DefaultLifecycleExecutor.forkLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 739	
      	DefaultLifecycleExecutor.executeGoals(List, Stack, MavenSession, MavenProject) line: 530	
      	DefaultLifecycleExecutor.executeGoalWithLifecycle(String, Stack, MavenSession, Map, MavenProject, Lifecycle) line: 480	
      	DefaultLifecycleExecutor.forkProjectLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 896	
      	DefaultLifecycleExecutor.forkLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 739	
      	DefaultLifecycleExecutor.executeGoals(List, Stack, MavenSession, MavenProject) line: 530	
      	DefaultLifecycleExecutor.executeGoalWithLifecycle(String, Stack, MavenSession, Map, MavenProject, Lifecycle) line: 480	
      	DefaultLifecycleExecutor.forkProjectLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 896	
      	DefaultLifecycleExecutor.forkLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 739	
      	DefaultLifecycleExecutor.executeGoals(List, Stack, MavenSession, MavenProject) line: 530	
      	DefaultLifecycleExecutor.executeGoalWithLifecycle(String, Stack, MavenSession, Map, MavenProject, Lifecycle) line: 480	
      	DefaultLifecycleExecutor.forkProjectLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 896	
      	DefaultLifecycleExecutor.forkLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 739	
      	DefaultLifecycleExecutor.executeGoals(List, Stack, MavenSession, MavenProject) line: 530	
      	DefaultLifecycleExecutor.executeGoalWithLifecycle(String, Stack, MavenSession, Map, MavenProject, Lifecycle) line: 480	
      	DefaultLifecycleExecutor.forkProjectLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 896	
      	DefaultLifecycleExecutor.forkLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 739	
      	DefaultLifecycleExecutor.executeGoals(List, Stack, MavenSession, MavenProject) line: 530	
      	DefaultLifecycleExecutor.executeGoalWithLifecycle(String, Stack, MavenSession, Map, MavenProject, Lifecycle) line: 480	
      	DefaultLifecycleExecutor.forkProjectLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 896	
      	DefaultLifecycleExecutor.forkLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 739	
      	DefaultLifecycleExecutor.executeGoals(List, Stack, MavenSession, MavenProject) line: 530	
      	DefaultLifecycleExecutor.executeGoalWithLifecycle(String, Stack, MavenSession, Map, MavenProject, Lifecycle) line: 480	
      	DefaultLifecycleExecutor.forkProjectLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 896	
      	DefaultLifecycleExecutor.forkLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 739	
      	DefaultLifecycleExecutor.executeGoals(List, Stack, MavenSession, MavenProject) line: 530	
      	DefaultLifecycleExecutor.executeGoalWithLifecycle(String, Stack, MavenSession, Map, MavenProject, Lifecycle) line: 480	
      	DefaultLifecycleExecutor.forkProjectLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 896	
      	DefaultLifecycleExecutor.forkLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 739	
      	DefaultLifecycleExecutor.executeGoals(List, Stack, MavenSession, MavenProject) line: 530	
      	DefaultLifecycleExecutor.executeGoalWithLifecycle(String, Stack, MavenSession, Map, MavenProject, Lifecycle) line: 480	
      	DefaultLifecycleExecutor.forkProjectLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 896	
      	DefaultLifecycleExecutor.forkLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 739	
      	DefaultLifecycleExecutor.executeGoals(List, Stack, MavenSession, MavenProject) line: 530	
      	DefaultLifecycleExecutor.executeGoalWithLifecycle(String, Stack, MavenSession, Map, MavenProject, Lifecycle) line: 480	
      	DefaultLifecycleExecutor.forkProjectLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 896	
      	DefaultLifecycleExecutor.forkLifecycle(MojoDescriptor, Stack, MavenSession, MavenProject) line: 739	
      	DefaultLifecycleExecutor.executeGoals(List, Stack, MavenSession, MavenProject) line: 510	
      	DefaultLifecycleExecutor.executeStandaloneGoal(String, Stack, MavenSession, MavenProject) line: 493	
      	DefaultLifecycleExecutor.executeGoal(String, MavenSession, MavenProject) line: 463	
      	DefaultLifecycleExecutor.executeGoalAndHandleFailures(String, MavenSession, MavenProject, EventDispatcher, String, ReactorManager, long, String) line: 311	
      	DefaultLifecycleExecutor.executeTaskSegments(List, ReactorManager, MavenSession, MavenProject, EventDispatcher) line: 278	
      	DefaultLifecycleExecutor.execute(MavenSession, ReactorManager, EventDispatcher) line: 143	
      	DefaultMaven.doExecute(MavenExecutionRequest, EventDispatcher) line: 333	
      	DefaultMaven.execute(MavenExecutionRequest) line: 126	
      	MavenCli.main(String[], ClassWorld) line: 280	
      	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
      	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39	
      	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25	
      	Method.invoke(Object, Object[]) line: 324	
      	Launcher.launchEnhanced(String[]) line: 315	
      	Launcher.launch(String[]) line: 255	
      	Launcher.mainWithExitCode(String[]) line: 430	
      	Launcher.main(String[]) line: 375	
      

      I put a small patch to break this, but I am not confident of potential side effects. Thanks to review it.

      1. infinite-loop.diff
        0.9 kB
        Vincent Siveton
      2. MNG-3221-maven-uml-plugin.diff
        1 kB
        Vincent Siveton
      3. MNG-3221-r633352.diff
        0.9 kB
        Vincent Siveton

        Activity

        Hide
        brianfox brianfox added a comment -

        seems ok to me.

        Show
        brianfox brianfox added a comment - seems ok to me.
        Hide
        brianfox brianfox added a comment -

        bumping to 2.0.9. If we get IT tests for these before 2.0.8 is final, we can take a look

        Show
        brianfox brianfox added a comment - bumping to 2.0.9. If we get IT tests for these before 2.0.8 is final, we can take a look
        Hide
        John Casey added a comment -

        This patch looks like it will prevent any @execute phase="xxx" from running, since the check is a truism...targetPhase is set to mojoDescriptor.getExecutePhase(), then later, the forked execution won't run if ( mojoDescriptor.getExecutionPhase().equals( targetPhase) )...in other words, nothing modifies targetPhase, and the only way the forked phase will run is if targetPhase is modified...

        Can you provide some tests that display this problem broken, then fixed with the patch?

        Show
        John Casey added a comment - This patch looks like it will prevent any @execute phase="xxx" from running, since the check is a truism...targetPhase is set to mojoDescriptor.getExecutePhase(), then later, the forked execution won't run if ( mojoDescriptor.getExecutionPhase().equals( targetPhase) )...in other words, nothing modifies targetPhase, and the only way the forked phase will run is if targetPhase is modified... Can you provide some tests that display this problem broken, then fixed with the patch?
        Hide
        brianfox brianfox added a comment -

        Still no way to replicate, bumping again.

        Show
        brianfox brianfox added a comment - Still no way to replicate, bumping again.
        Hide
        Vincent Siveton added a comment -

        Thanks for the reminder, Brian, I totally forgot it

        Here are the steps to reproduce it:
        1) svn co https://svn.apache.org/repos/asf/maven/sandbox/trunk/plugins/maven-uml-plugin and do mvn install (mvn 2.0.8)
        2) mvn site You will see:

        ...
        [INFO] Preparing uml:uml
        [INFO] Preparing uml:uml
        [INFO] Preparing uml:uml
        ...
        

        3) apply MNG-3221-r633352.diff, mvn install, unzip for instance apache-maven-2.0.9-SNAPSHOT-bin.zip and set new M2_HOME
        4) apply MNG-3221-maven-uml-plugin.diff and mvn install
        5) mvn site (with new M2_HOME) should not produce the infinite loop

        Hope that I don't forget anything

        Show
        Vincent Siveton added a comment - Thanks for the reminder, Brian, I totally forgot it Here are the steps to reproduce it: 1) svn co https://svn.apache.org/repos/asf/maven/sandbox/trunk/plugins/maven-uml-plugin and do mvn install (mvn 2.0.8) 2) mvn site You will see: ... [INFO] Preparing uml:uml [INFO] Preparing uml:uml [INFO] Preparing uml:uml ... 3) apply MNG-3221 -r633352.diff, mvn install, unzip for instance apache-maven-2.0.9-SNAPSHOT-bin.zip and set new M2_HOME 4) apply MNG-3221 -maven-uml-plugin.diff and mvn install 5) mvn site (with new M2_HOME) should not produce the infinite loop Hope that I don't forget anything
        Hide
        Vincent Siveton added a comment -

        Updated fix version since test case is provided

        Show
        Vincent Siveton added a comment - Updated fix version since test case is provided
        Hide
        John Casey added a comment -

        I've found a more general approach to prevent this looping problem. My approach should also detect multi-mojo forking cycles, because it adds phase tracking to the forkEntryPoints stack, and modifies the behavior in cases of MojoDescriptor.getExecutionGoal() != null where this wasn't checked before.

        I've tested it vs. the test scenario above, and where it failed prior to this fix, it's fine now.

        I still need to figure out how/if I can make an integration test out of a simplified version of this test scenario, that won't bring down the whole test run with an infinite loop...I'm open to ideas here.

        Show
        John Casey added a comment - I've found a more general approach to prevent this looping problem. My approach should also detect multi-mojo forking cycles, because it adds phase tracking to the forkEntryPoints stack, and modifies the behavior in cases of MojoDescriptor.getExecutionGoal() != null where this wasn't checked before. I've tested it vs. the test scenario above, and where it failed prior to this fix, it's fine now. I still need to figure out how/if I can make an integration test out of a simplified version of this test scenario, that won't bring down the whole test run with an infinite loop...I'm open to ideas here.
        Hide
        John Casey added a comment -

        The bug is fixed, and I've made a note on my personal TODO list to find a way to integration-test this.

        Show
        John Casey added a comment - The bug is fixed, and I've made a note on my personal TODO list to find a way to integration-test this.
        Hide
        John Casey added a comment -

        I've reverted the original fix I committed for this issue, and instead added code to remove report mojos that are already in the fork-points stack, just like we're doing for normal mojos now. This should provide behavior consistent with the rest of the build where forked executions are concerned.

        Show
        John Casey added a comment - I've reverted the original fix I committed for this issue, and instead added code to remove report mojos that are already in the fork-points stack, just like we're doing for normal mojos now. This should provide behavior consistent with the rest of the build where forked executions are concerned.

          People

          • Assignee:
            John Casey
            Reporter:
            Vincent Siveton
          • Votes:
            1 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: