Skip to content
Permalink
Browse files

Merge pull request #65 from jglick/isReady-JENKINS-25890

[JENKINS-25890] Deadlock
  • Loading branch information
jglick committed Mar 3, 2015
2 parents 8fe11e0 + 790a545 commit 8740a01d48c36289efaca6d2af7714cc7718594e
@@ -5,6 +5,7 @@ Only noting significant user-visible or major API changes, not internal code cle
## 1.3 (upcoming)

### User changes
* JENKINS-25890: deadlock during restart.
* Fixed some file handle leaks caught by tests which may have affected Windows masters.
* JENKINS-25779: snippet generator now omits default values of complex steps.
* Ability to configure project display name.
@@ -650,7 +650,6 @@ public static void finish(final boolean terminate) {
});
}

@RandomlyFails("TODO JENKINS-25890 sometimes triggers a deadlock after restart")
@Issue("JENKINS-26513")
@Test public void executorStepRestart() {
story.addStep(new Statement() {
@@ -74,7 +74,7 @@ public void setResult(Result r) {
}

@Override
public boolean isReady() throws IOException, InterruptedException {
public boolean isReady() {
return base.isReady();
}

@@ -59,6 +59,7 @@
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import jenkins.util.Timer;
import org.codehaus.groovy.runtime.InvokerInvocationException;

import static org.jenkinsci.plugins.workflow.cps.persistence.PersistenceContext.*;
@@ -215,7 +216,7 @@ public String getDisplayName() {
*
* This can block for the entire duration of the PREPARING state.
*/
@CheckForNull CpsThread getThreadSynchronously() throws InterruptedException, IOException {
private @CheckForNull CpsThread getThreadSynchronously() throws InterruptedException, IOException {
try {
CpsThreadGroup g = getProgramPromise().get();
return getThread(g);
@@ -224,13 +225,24 @@ public String getDisplayName() {
}
}

private @Nonnull ListenableFuture<CpsThreadGroup> getProgramPromise() throws IOException {
ListenableFuture<CpsThreadGroup> pp = getFlowExecution().programPromise;
assert pp != null;
return pp;
private @Nonnull ListenableFuture<CpsThreadGroup> getProgramPromise() {
final SettableFuture<CpsThreadGroup> f = SettableFuture.create();
// TODO is there some more convenient way of writing this using Futures.transform?
Timer.get().submit(new Runnable() {
@Override public void run() {
try {
ListenableFuture<CpsThreadGroup> pp = getFlowExecution().programPromise;
assert pp != null;
f.set(pp.get());
} catch (Exception x) { // from getFlowExecution() or get()
f.setException(x);
}
}
});
return f;
}

@Override public boolean isReady() throws IOException, InterruptedException {
@Override public boolean isReady() {
return getProgramPromise().isDone();
}

@@ -83,7 +83,7 @@
* May be called to break deadlocks during reloading.
* @return true normally, false if we are still reloading the context, for example during unpickling
*/
public abstract boolean isReady() throws IOException, InterruptedException;
public abstract boolean isReady();

/**
* Requests that any state held by the {@link StepExecution} be saved to disk.

0 comments on commit 8740a01

Please sign in to comment.
You can’t perform that action at this time.