diff --git a/core/src/main/java/hudson/model/CheckPoint.java b/core/src/main/java/hudson/model/CheckPoint.java index 1e95667c75e4..7a5e330af6ad 100644 --- a/core/src/main/java/hudson/model/CheckPoint.java +++ b/core/src/main/java/hudson/model/CheckPoint.java @@ -28,6 +28,7 @@ import hudson.tasks.Builder; import hudson.tasks.junit.JUnitResultArchiver; import hudson.scm.SCM; +import javax.annotation.Nonnull; /** * Provides a mechanism for synchronizing build executions in the face of concurrent builds. @@ -141,7 +142,18 @@ public void report() { * If the build (represented by the calling executor thread) is aborted while it's waiting. */ public void block() throws InterruptedException { - Run.waitForCheckpoint(this); + Run.waitForCheckpoint(this, null, null); + } + + /** + * Like {@link #block()} but allows for richer logging. + * @param listener an optional listener to which + * @param waiter a description of what component is requesting the wait, such as {@link Descriptor#getDisplayName} + * @throws InterruptedException if the build is aborted while waiting + * @since 1.528 + */ + public void block(@Nonnull BuildListener listener, @Nonnull String waiter) throws InterruptedException { + Run.waitForCheckpoint(this, listener, waiter); } /** diff --git a/core/src/main/java/hudson/model/Run.java b/core/src/main/java/hudson/model/Run.java index 1b651c207bc7..2c9fa11317a3 100644 --- a/core/src/main/java/hudson/model/Run.java +++ b/core/src/main/java/hudson/model/Run.java @@ -1403,7 +1403,7 @@ private void removeRunFromParent() { /** * @see CheckPoint#block() */ - /*package*/ static void waitForCheckpoint(CheckPoint id) throws InterruptedException { + /*package*/ static void waitForCheckpoint(CheckPoint id, @CheckForNull BuildListener listener, @CheckForNull String waiter) throws InterruptedException { while(true) { Run b = RunnerStack.INSTANCE.peek().getBuild().getPreviousBuildInProgress(); if(b==null) return; // no pending earlier build @@ -1413,7 +1413,7 @@ private void removeRunFromParent() { Thread.sleep(0); continue; } - if(runner.checkpoints.waitForCheckPoint(id)) + if(runner.checkpoints.waitForCheckPoint(id, listener, waiter)) return; // confirmed that the previous build reached the check point // the previous build finished without ever reaching the check point. try again. @@ -1449,13 +1449,19 @@ protected synchronized void report(CheckPoint identifier) { notifyAll(); } - protected synchronized boolean waitForCheckPoint(CheckPoint identifier) throws InterruptedException { + protected synchronized boolean waitForCheckPoint(CheckPoint identifier, @CheckForNull BuildListener listener, @CheckForNull String waiter) throws InterruptedException { final Thread t = Thread.currentThread(); final String oldName = t.getName(); - t.setName(oldName+" : waiting for "+identifier+" on "+getFullDisplayName()); + t.setName(oldName + " : waiting for " + identifier + " on " + getFullDisplayName() + " from " + waiter); try { - while(!allDone && !checkpoints.contains(identifier)) + boolean first = true; + while (!allDone && !checkpoints.contains(identifier)) { + if (first && listener != null && waiter != null) { + listener.getLogger().println(Messages.Run__is_waiting_for_a_checkpoint_on_(waiter, getFullDisplayName())); + } wait(); + first = false; + } return checkpoints.contains(identifier); } finally { t.setName(oldName); diff --git a/core/src/main/java/hudson/tasks/BuildStepMonitor.java b/core/src/main/java/hudson/tasks/BuildStepMonitor.java index 5bcb3068001c..cd7bab7e38e8 100644 --- a/core/src/main/java/hudson/tasks/BuildStepMonitor.java +++ b/core/src/main/java/hudson/tasks/BuildStepMonitor.java @@ -4,6 +4,7 @@ import hudson.model.BuildListener; import hudson.model.CheckPoint; import hudson.Launcher; +import hudson.model.Describable; import java.io.IOException; @@ -22,7 +23,11 @@ public boolean perform(BuildStep bs, AbstractBuild build, Launcher launcher, Bui STEP { public boolean perform(BuildStep bs, AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { CheckPoint cp = new CheckPoint(bs.getClass().getName(),bs.getClass()); - cp.block(); + if (bs instanceof Describable) { + cp.block(listener, ((Describable) bs).getDescriptor().getDisplayName()); + } else { + cp.block(); + } try { return bs.perform(build,launcher,listener); } finally { @@ -32,7 +37,11 @@ public boolean perform(BuildStep bs, AbstractBuild build, Launcher launcher, Bui }, BUILD { public boolean perform(BuildStep bs, AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { - CheckPoint.COMPLETED.block(); + if (bs instanceof Describable) { + CheckPoint.COMPLETED.block(listener, ((Describable) bs).getDescriptor().getDisplayName()); + } else { + CheckPoint.COMPLETED.block(); + } return bs.perform(build,launcher,listener); } }; diff --git a/core/src/main/java/hudson/tasks/junit/JUnitResultArchiver.java b/core/src/main/java/hudson/tasks/junit/JUnitResultArchiver.java index a2548bdc569a..50d5d784e839 100644 --- a/core/src/main/java/hudson/tasks/junit/JUnitResultArchiver.java +++ b/core/src/main/java/hudson/tasks/junit/JUnitResultArchiver.java @@ -156,7 +156,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, action.setData(data); - CHECKPOINT.block(); + CHECKPOINT.block(listener, getDescriptor().getDisplayName()); } catch (AbortException e) { if (build.getResult() == Result.FAILURE) diff --git a/core/src/main/resources/hudson/model/Messages.properties b/core/src/main/resources/hudson/model/Messages.properties index f7fdf4011680..03bf5d9416be 100644 --- a/core/src/main/resources/hudson/model/Messages.properties +++ b/core/src/main/resources/hudson/model/Messages.properties @@ -205,6 +205,7 @@ ResultTrend.StillFailing=Still failing ResultTrend.StillUnstable=Still unstable ResultTrend.Success=Success ResultTrend.Unstable=Unstable +Run._is_waiting_for_a_checkpoint_on_={0} is waiting for a checkpoint on {1} Run.BuildAborted=Build was aborted Run.MarkedExplicitly=This record is explicitly marked to be kept. Run.Permissions.Title=Run