Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-31953

Stopping build running parallel branches can doubly deliver stop

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Minor Minor
    • workflow-cps-plugin
    • None

      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.

            Unassigned Unassigned
            jglick Jesse Glick
            Votes:
            2 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated: