Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FIXED JENKINS-9203] in light of 9c96561, I think the proper fix is t…
…o define a mechanism to abort with status.
  • Loading branch information
kohsuke committed Jun 17, 2011
1 parent df5862c commit a3354b1
Show file tree
Hide file tree
Showing 10 changed files with 62 additions and 8 deletions.
4 changes: 3 additions & 1 deletion changelog.html
Expand Up @@ -55,7 +55,9 @@
<!-- Record your changes in the trunk here. -->
<div id="trunk" style="display:none"><!--=TRUNK-BEGIN=-->
<ul class=image>
<li class=>
<li class=bug>
Defined a proper way to interrupt the build and mark it as a failure.
(<a href="http://issues.jenkins-ci.org/browse/JENKINS-9203">issue 9203</a>)
<li class=rfe>
About page should not autorefresh
(<a href="http://issues.jenkins-ci.org/browse/JENKINS-9967">issue 9967</a>)
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/hudson/matrix/MatrixBuild.java
Expand Up @@ -306,7 +306,7 @@ protected Result doRun(BuildListener listener) throws Exception {
return r;
} catch( InterruptedException e ) {
logger.println("Aborted");
return Result.ABORTED;
return Executor.currentExecutor().abortResult();
} catch (AggregatorFailureException e) {
return Result.FAILURE;
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/hudson/model/Build.java
Expand Up @@ -139,7 +139,7 @@ protected Result doRun(BuildListener listener) throws Exception {
if(!build(listener,project.getBuilders()))
r = FAILURE;
} catch (InterruptedException e) {
r = ABORTED;
r = Executor.currentExecutor().abortResult();
throw e;
} finally {
if (r != null) setResult(r);
Expand Down
29 changes: 29 additions & 0 deletions core/src/main/java/hudson/model/Executor.java
Expand Up @@ -82,13 +82,41 @@ public class Executor extends Thread implements ModelObject {

private boolean induceDeath;

/**
* When the executor is interrupted, we allow the code that interrupted the thread to override the
* result code it prefers.
*/
private Result interruptStatus;

public Executor(Computer owner, int n) {
super("Executor #"+n+" for "+owner.getDisplayName());
this.owner = owner;
this.queue = Jenkins.getInstance().getQueue();
this.number = n;
}

@Override
public void interrupt() {
interrupt(Result.ABORTED);
}

/**
* Interrupt the execution,
* but instead of marking the build as aborted, mark it as specified result.
*
* @since 1.417
*/
public void interrupt(Result result) {
interruptStatus = result;
super.interrupt();
}

public Result abortResult() {
Result r = interruptStatus;
if (r==null) r = Result.ABORTED; // this is when we programmatically throw InterruptedException instead of calling the interrupt method.
return r;
}

@Override
public void run() {
// run as the system user. see ACL.SYSTEM for more discussion about why this is somewhat broken
Expand All @@ -99,6 +127,7 @@ public void run() {
while(shouldRun()) {
executable = null;
workUnit = null;
interruptStatus = null;

synchronized(owner) {
if(owner.getNumExecutors()<owner.getExecutors().size()) {
Expand Down
3 changes: 3 additions & 0 deletions core/src/main/java/hudson/model/Result.java
Expand Up @@ -65,6 +65,9 @@ public final class Result implements Serializable, CustomExportedBean {
public static final Result NOT_BUILT = new Result("NOT_BUILT",BallColor.GREY,3);
/**
* The build was manually aborted.
*
* If you are catching {@link InterruptedException} and interpreting it as {@link #ABORTED},
* you should check {@link Executor#abortResult()} instead (starting 1.417.)
*/
public static final Result ABORTED = new Result("ABORTED",BallColor.ABORTED,4);

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/hudson/model/Run.java
Expand Up @@ -1388,7 +1388,7 @@ protected final void run(Runner job) {
LOGGER.log(FINE, "Build "+this+" aborted",e);
} catch( InterruptedException e) {
// aborted
result = Result.ABORTED;
result = Executor.currentExecutor().abortResult();
listener.getLogger().println(Messages.Run_BuildAborted());
LOGGER.log(Level.INFO,toString()+" aborted",e);
} catch( Throwable e ) {
Expand Down
3 changes: 2 additions & 1 deletion maven-plugin/src/main/java/hudson/maven/Maven3Builder.java
Expand Up @@ -27,6 +27,7 @@
import hudson.maven.MavenBuild.ProxyImpl2;
import hudson.maven.util.ExecutionEventLogger;
import hudson.model.BuildListener;
import hudson.model.Executor;
import jenkins.model.Jenkins;
import hudson.model.Result;
import hudson.remoting.Channel;
Expand Down Expand Up @@ -141,7 +142,7 @@ public Result call() throws IOException {
g.cancel(true);
// FIXME messages
listener.getLogger().println("build aborted");
return Result.ABORTED;
return Executor.currentExecutor().abortResult();
} catch (ExecutionException e) {
// FIXME messages
e.printStackTrace(listener.error("async build failed"));
Expand Down
3 changes: 2 additions & 1 deletion maven-plugin/src/main/java/hudson/maven/MavenBuilder.java
Expand Up @@ -29,6 +29,7 @@
import hudson.maven.agent.PluginManagerListener;
import hudson.maven.reporters.SurefireArchiver;
import hudson.model.BuildListener;
import hudson.model.Executor;
import hudson.model.Result;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
Expand Down Expand Up @@ -178,7 +179,7 @@ public Result call() throws IOException {
for (Future<?> g : futures)
g.cancel(true);
listener.getLogger().println(Messages.MavenBuilder_Aborted());
return Result.ABORTED;
return Executor.currentExecutor().abortResult();
} catch (ExecutionException e) {
e.printStackTrace(listener.error(Messages.MavenBuilder_AsyncFailed()));
}
Expand Down
Expand Up @@ -43,6 +43,7 @@
import hudson.model.Cause.UpstreamCause;
import hudson.model.Computer;
import hudson.model.Environment;
import hudson.model.Executor;
import hudson.model.Fingerprint;
import jenkins.model.Jenkins;
import hudson.model.ParameterDefinition;
Expand Down Expand Up @@ -746,7 +747,7 @@ protected Result doRun(final BuildListener listener) throws Exception {
}
}
} catch (InterruptedException e) {
r = ABORTED;
r = Executor.currentExecutor().abortResult();
throw e;
} finally {
if (r != null) {
Expand All @@ -771,7 +772,7 @@ protected Result doRun(final BuildListener listener) throws Exception {
return Result.FAILURE;
} catch (InterruptedIOException e) {
e.printStackTrace(listener.error("Aborted Maven execution for InterruptedIOException"));
return Result.ABORTED;
return Executor.currentExecutor().abortResult();
} catch (IOException e) {
e.printStackTrace(listener.error(Messages.MavenModuleSetBuild_FailedToParsePom()));
return Result.FAILURE;
Expand Down
17 changes: 17 additions & 0 deletions test/src/test/java/hudson/model/AbortedFreeStyleBuildTest.java
Expand Up @@ -25,4 +25,21 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListen
throw new InterruptedException();
}
}

@Bug(9203)
public void testInterruptAsFailure() throws Exception {
FreeStyleProject project = createFreeStyleProject();
TestBuildWrapper wrapper = new TestBuildWrapper();
project.getBuildWrappersList().add(wrapper);
project.getBuildersList().add(new TestBuilder() {
@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
Executor.currentExecutor().interrupt(Result.FAILURE);
throw new InterruptedException();
}
});
Run build = project.scheduleBuild2(0).get();
assertEquals(Result.FAILURE, build.getResult());
assertEquals(Result.FAILURE, wrapper.buildResultInTearDown);
}
}

0 comments on commit a3354b1

Please sign in to comment.