Stopping build running parallel branches can doubly deliver stop

This issue is archived. You can view it, but you can't modify it. Learn more

XMLWordPrintable

      Noticed as part of JENKINS-31769:

      If you run a build with parallel branches, some of which have already completed but others of which are still running, and you abort the build, StepExecution.stop will be run twice on the leaf steps in at least some of the live branches: once directly from CpsFlowExecution.interrupt, once indirectly via ParallelStepExecution.stop.

      This despite the fact that (as per JENKINS-26148) stop is only supposed to be delivered to the innermost executions. ParallelStepExecution is incorrectly listed as one of these (along with its living children). Reproducible in a test as follows:

      diff --git a/aggregator/src/test/java/org/jenkinsci/plugins/workflow/CpsFlowExecutionTest.java b/aggregator/src/test/java/org/jenkinsci/plugins/workflow/CpsFlowExecutionTest.java
      index bfa48b3..57ee251 100644
      --- a/aggregator/src/test/java/org/jenkinsci/plugins/workflow/CpsFlowExecutionTest.java
      +++ b/aggregator/src/test/java/org/jenkinsci/plugins/workflow/CpsFlowExecutionTest.java
      @@ -34,6 +34,7 @@ import java.util.List;
       import java.util.ListIterator;
       import org.codehaus.groovy.transform.ASTTransformationVisitor;
       import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
      +import org.jenkinsci.plugins.workflow.cps.CpsFlowExecution;
       import org.jenkinsci.plugins.workflow.cps.CpsStepContext;
       import org.jenkinsci.plugins.workflow.flow.FlowExecution;
       import org.jenkinsci.plugins.workflow.job.WorkflowJob;
      @@ -42,14 +43,17 @@ import org.jenkinsci.plugins.workflow.steps.StepDescriptor;
       import org.jenkinsci.plugins.workflow.steps.StepExecution;
       import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep;
       import static org.junit.Assert.*;
      +import org.junit.ClassRule;
       import org.junit.Rule;
       import org.junit.Test;
       import org.junit.runners.model.Statement;
      +import org.jvnet.hudson.test.BuildWatcher;
       import org.jvnet.hudson.test.MemoryAssert;
       import org.jvnet.hudson.test.RestartableJenkinsRule;
       
       public class CpsFlowExecutionTest {
       
      +    @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
           @Rule public RestartableJenkinsRule story = new RestartableJenkinsRule();
           
           private static WeakReference<ClassLoader> LOADER;
      @@ -158,6 +162,8 @@ public class CpsFlowExecutionTest {
                       SemaphoreStep.waitForStart("seven/1", b);
                       assertStepExecutions(e, "parallel {}", "node {}", "semaphore", "semaphore");
                       SemaphoreStep.success("six/1", null);
      +                ((CpsFlowExecution) e).waitForSuspension();
      +                assertStepExecutions(e, "parallel {}", "semaphore");
                       SemaphoreStep.success("seven/1", null);
                       SemaphoreStep.waitForStart("eight/1", b);
                       assertStepExecutions(e, "semaphore");
      

      Somehow the set of CpsThread is too small, and so the trick in getCurrentExecutions does not work as advertised.

            Assignee:
            Unassigned
            Reporter:
            Jesse Glick
            Archiver:
            Jenkins Service Account

              Created:
              Updated:
              Archived: