Skip to content
This repository has been archived by the owner on Dec 15, 2021. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
[FIXED JENKINS-25550] Hard kill.
  • Loading branch information
jglick committed Jun 17, 2015
1 parent 2f0fef4 commit 60a0db7
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -4,6 +4,7 @@ Only noting significant user-visible or major API changes, not internal code cle

## 1.9 (upcoming)

* [JENKINS-25550](https://issues.jenkins-ci.org/browse/JENKINS-25550): flow builds hung due to a buggy step (and certain erroneous scripts) can now be forcibly stopped by clicking the stop button three times.
* [JENKINS-28756](https://issues.jenkins-ci.org/browse/JENKINS-28756): dropdown for _General SCM_ step incorrectly listed SCMs not compatible with Workflow.

## 1.8 (Jun 01 2015)
Expand Down
Expand Up @@ -25,12 +25,14 @@
package org.jenkinsci.plugins.workflow;

import hudson.model.BallColor;
import hudson.model.Executor;
import hudson.model.Item;
import hudson.model.ParametersAction;
import hudson.model.ParametersDefinitionProperty;
import hudson.model.Result;
import hudson.model.StringParameterDefinition;
import hudson.model.StringParameterValue;
import hudson.model.TaskListener;
import hudson.model.User;
import hudson.model.queue.QueueTaskFuture;
import hudson.security.ACL;
Expand All @@ -45,18 +47,26 @@
import org.jenkinsci.plugins.workflow.cps.CpsFlowExecution;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl;
import org.jenkinsci.plugins.workflow.steps.AbstractStepExecutionImpl;
import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl;
import org.jenkinsci.plugins.workflow.steps.StepContextParameter;
import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep;

import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.TestExtension;
import org.jvnet.hudson.test.recipes.LocalData;
import org.kohsuke.stapler.DataBoundConstructor;

public class WorkflowRunTest {

@ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
@Rule public JenkinsRule r = new JenkinsRule();

WorkflowJob p;
Expand Down Expand Up @@ -201,4 +211,48 @@ public void contextInjectionOfSubParameters() throws Exception {
r.assertBuildStatusSuccess(JenkinsRuleExt.waitForCompletion(b));
}

@Issue("JENKINS-25550")
@Test public void hardKill() throws Exception {
p = r.jenkins.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition("zombie()"));
WorkflowRun b = p.scheduleBuild2(0).waitForStart();
JenkinsRuleExt.waitForMessage("undead", b);
Executor ex = b.getExecutor();
assertNotNull(ex);
ex.interrupt();
JenkinsRuleExt.waitForMessage("bwahaha org.jenkinsci.plugins.workflow.steps.FlowInterruptedException #1", b);
ex.interrupt();
JenkinsRuleExt.waitForMessage("bwahaha org.jenkinsci.plugins.workflow.steps.FlowInterruptedException #2", b);
ex.interrupt();
JenkinsRuleExt.waitForMessage("Hard kill!", b);
JenkinsRuleExt.waitForCompletion(b);
r.assertBuildStatus(Result.ABORTED, b);
}
public static class Zombie extends AbstractStepImpl {
@DataBoundConstructor public Zombie() {}
public static class Execution extends AbstractStepExecutionImpl {
@StepContextParameter private transient TaskListener listener;
int count;
@Override public boolean start() throws Exception {
listener.getLogger().println("undead");
return false;
}
@Override public void stop(Throwable cause) throws Exception {
listener.getLogger().println("bwahaha " + cause + " #" + ++count);
}

}
@TestExtension("hardKill") public static class DescriptorImpl extends AbstractStepDescriptorImpl {
public DescriptorImpl() {
super(Execution.class);
}
@Override public String getFunctionName() {
return "zombie";
}
@Override public String getDisplayName() {
return "zombie";
}
}
}

}
Expand Up @@ -68,6 +68,7 @@
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;
Expand Down Expand Up @@ -202,10 +203,16 @@ public WorkflowRun(WorkflowJob job, File dir) throws IOException {

private AsynchronousExecution sleep() {
final AsynchronousExecution asynchronousExecution = new AsynchronousExecution() {
AtomicInteger interruptionCount = new AtomicInteger();
@Override public void interrupt(boolean forShutdown) {
if (forShutdown) {
return;
}
if (interruptionCount.incrementAndGet() == 3) {

This comment has been minimized.

Copy link
@cnmcavoy

cnmcavoy Nov 17, 2015

Why isn't this >=? If there has been more than 3 interruptions, there is no way for someone to "undo" one and get back to 3 to hard kill a job.

listener.getLogger().println("Hard kill!");
finish(Result.ABORTED);
return;
}
try {
execution.interrupt(Result.ABORTED);
} catch (Exception x) {
Expand Down Expand Up @@ -503,7 +510,7 @@ public boolean hasntStartedYet() {

@Exported
@Override protected boolean isInProgress() {
return execution != null && !execution.isComplete();
return execution != null && !execution.isComplete() && (completed == null || !completed.get());
}

@Override public boolean isLogUpdated() {
Expand Down

0 comments on commit 60a0db7

Please sign in to comment.