From 2870bd01d2ffcd065e94bd3f70b20f7a20ed364a Mon Sep 17 00:00:00 2001 From: Devin Nusbaum Date: Thu, 5 Dec 2019 13:21:27 -0500 Subject: [PATCH 1/2] [JENKINS-60354] Add flag to FlowInterruptedException to indicate actual interruptions --- .../steps/FlowInterruptedException.java | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jenkinsci/plugins/workflow/steps/FlowInterruptedException.java b/src/main/java/org/jenkinsci/plugins/workflow/steps/FlowInterruptedException.java index 3e5ea95..5c01c77 100644 --- a/src/main/java/org/jenkinsci/plugins/workflow/steps/FlowInterruptedException.java +++ b/src/main/java/org/jenkinsci/plugins/workflow/steps/FlowInterruptedException.java @@ -44,7 +44,8 @@ /** * Special exception that can be thrown out of {@link StepContext#onFailure} to indicate that the flow was aborted from the inside. - * (This could be caught like any other exception and rethrown or ignored. It only takes effect if thrown all the way up.) + * (This could be caught like any other exception and rethrown or ignored. It only takes effect if thrown all the way up. + * Consumers, such as steps, may find {@link #isActualInterruption} useful in deciding whether to ignore or rethrow the exception.) *

No stack trace is printed (except by {@link #getCause} and/or {@link #getSuppressed} if present), * and you can control the {@link Result} and {@link CauseOfInterruption}. *

Analogous to {@link Executor#interrupt(Result, CauseOfInterruption...)} but does not assume we are running inside an executor thread. @@ -53,8 +54,16 @@ */ public final class FlowInterruptedException extends InterruptedException { + private static final long serialVersionUID = 630482382622970136L; + private final @Nonnull Result result; private final @Nonnull List causes; + /** + * If true, this exception represents an actual build interruption, rather than a general error with a result and + * no stack trace. + * Used by steps like {@code RetryStep} to decide whether to handle or rethrow a {@link FlowInterruptedException}. + */ + private final boolean actualInterruption; /** * Creates a new exception. @@ -64,6 +73,19 @@ public final class FlowInterruptedException extends InterruptedException { public FlowInterruptedException(@Nonnull Result result, @Nonnull CauseOfInterruption... causes) { this.result = result; this.causes = Arrays.asList(causes); + this.actualInterruption = false; + } + + /** + * Creates a new exception. + * @param result the desired result for the flow, typically {@link Result#ABORTED} + * @param causes any indications + * @param actualInterruption true if this is an actual build interruption (e.g. the user wants to abort the build) + */ + public FlowInterruptedException(@Nonnull Result result, boolean actualInterruption, @Nonnull CauseOfInterruption... causes) { + this.result = result; + this.causes = Arrays.asList(causes); + this.actualInterruption = actualInterruption; } public @Nonnull Result getResult() { @@ -74,6 +96,10 @@ public FlowInterruptedException(@Nonnull Result result, @Nonnull CauseOfInterrup return causes; } + public boolean isActualInterruption() { + return actualInterruption; + } + /** * If a build catches this exception, it should use this method to report it. */ From 5cb7d364693185d26873102af3c8f3de158730f1 Mon Sep 17 00:00:00 2001 From: Devin Nusbaum Date: Mon, 9 Dec 2019 12:49:27 -0500 Subject: [PATCH 2/2] [JENKINS-60354] Switch actualInterruption default value to true --- .../workflow/steps/FlowInterruptedException.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jenkinsci/plugins/workflow/steps/FlowInterruptedException.java b/src/main/java/org/jenkinsci/plugins/workflow/steps/FlowInterruptedException.java index 5c01c77..fa6753a 100644 --- a/src/main/java/org/jenkinsci/plugins/workflow/steps/FlowInterruptedException.java +++ b/src/main/java/org/jenkinsci/plugins/workflow/steps/FlowInterruptedException.java @@ -62,8 +62,10 @@ public final class FlowInterruptedException extends InterruptedException { * If true, this exception represents an actual build interruption, rather than a general error with a result and * no stack trace. * Used by steps like {@code RetryStep} to decide whether to handle or rethrow a {@link FlowInterruptedException}. + * Non-null, except momentarily during deserialization before {@link #readResolve} sets the field to {@code true} + * for old instances serialized before this field was added. */ - private final boolean actualInterruption; + private Boolean actualInterruption = true; /** * Creates a new exception. @@ -73,7 +75,7 @@ public final class FlowInterruptedException extends InterruptedException { public FlowInterruptedException(@Nonnull Result result, @Nonnull CauseOfInterruption... causes) { this.result = result; this.causes = Arrays.asList(causes); - this.actualInterruption = false; + this.actualInterruption = true; } /** @@ -100,6 +102,13 @@ public boolean isActualInterruption() { return actualInterruption; } + private Object readResolve() { + if (actualInterruption == null) { + actualInterruption = true; + } + return this; + } + /** * If a build catches this exception, it should use this method to report it. */