提交 a5d848bc 编写于 作者: J Jesse Glick

[FIXED JENKINS-22560] Avoid deadlock by making AbstractBuild.runMixIn final.

(Forgot that Run’s are unmarshalled in place after a special constructor is called, so there is no need for readResolve or other tricks.)
Also calling RunListener.onDeleted outside of the Run lock to avoid problems with things like ChangeLogHistoryRunListener.
上级 8a174621
......@@ -58,6 +58,9 @@ Upcoming changes</a>
<li class=bug>
Fixed NPE from view new job name autocompletion since 1.553.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-22142">issue 22142</a>)
<li class='major bug'>
Deadlocks in concurrent builds under some conditions since 1.556.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-22560">issue 22560</a>)
<li class=rfe>
JNLP slaves are now handled through NIO-based remoting channels for better scalability.
</ul>
......
......@@ -71,7 +71,6 @@ import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.StringWriter;
import java.lang.ref.WeakReference;
import java.text.MessageFormat;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Calendar;
......@@ -156,7 +155,11 @@ public abstract class AbstractBuild<P extends AbstractProject<P,R>,R extends Abs
*/
protected transient List<Environment> buildEnvironments;
private transient LazyBuildMixIn.RunMixIn<P,R> runMixIn;
private transient final LazyBuildMixIn.RunMixIn<P,R> runMixIn = new LazyBuildMixIn.RunMixIn<P,R>() {
@Override protected R asRun() {
return _this();
}
};
protected AbstractBuild(P job) throws IOException {
super(job);
......@@ -174,14 +177,7 @@ public abstract class AbstractBuild<P extends AbstractProject<P,R>,R extends Abs
return getParent();
}
@Override public final synchronized LazyBuildMixIn.RunMixIn<P,R> getRunMixIn() {
if (runMixIn == null) {
runMixIn = new LazyBuildMixIn.RunMixIn<P,R>() {
@Override protected R asRun() {
return _this();
}
};
}
@Override public final LazyBuildMixIn.RunMixIn<P,R> getRunMixIn() {
return runMixIn;
}
......
......@@ -1445,17 +1445,19 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
* @throws IOException
* if we fail to delete.
*/
public synchronized void delete() throws IOException {
public void delete() throws IOException {
File rootDir = getRootDir();
if (!rootDir.isDirectory()) {
throw new IOException(this + ": " + rootDir + " looks to have already been deleted");
}
RunListener.fireDeleted(this);
synchronized (this) { // avoid holding a lock while calling plugin impls of onDeleted
// if we have a symlink, delete it, too
File link = new File(project.getBuildDir(), String.valueOf(getNumber()));
link.delete();
File rootDir = getRootDir();
if (!rootDir.isDirectory()) {
throw new IOException(this + ": " + rootDir + " looks to have already been deleted");
}
File tmp = new File(rootDir.getParentFile(),'.'+rootDir.getName());
if (tmp.exists()) {
......@@ -1474,6 +1476,7 @@ public abstract class Run <JobT extends Job<JobT,RunT>,RunT extends Run<JobT,Run
LOGGER.log(FINE, "{0}: {1} successfully deleted", new Object[] {this, rootDir});
removeRunFromParent();
}
}
@SuppressWarnings("unchecked") // seems this is too clever for Java's type system?
......
......@@ -280,7 +280,7 @@ public abstract class LazyBuildMixIn<JobT extends Job<JobT,RunT> & Queue.Task &
/**
* Accompanying helper for the run type.
* Stateful but should be held in a {@code transient} field.
* Stateful but should be held in a {@code transient final} field.
*/
public static abstract class RunMixIn<JobT extends Job<JobT,RunT> & Queue.Task & LazyBuildMixIn.LazyLoadingJob<JobT,RunT>, RunT extends Run<JobT,RunT> & LazyLoadingRun<JobT,RunT>> {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册