Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Foster2015-05-11 20:03:49 -0400
committerBob Foster2015-05-11 20:03:49 -0400
commitdc6ce42783fd17a3861b3e51963a2bd22f5b34ec (patch)
treeedd5ecf795fcaf6fd69c97c72457b8d1ab5de2ae
parent2b45c76ceba3a40d95771cd9c37974e3ac257409 (diff)
downloadorg.eclipse.hudson.core-dc6ce42783fd17a3861b3e51963a2bd22f5b34ec.tar.gz
org.eclipse.hudson.core-dc6ce42783fd17a3861b3e51963a2bd22f5b34ec.tar.xz
org.eclipse.hudson.core-dc6ce42783fd17a3861b3e51963a2bd22f5b34ec.zip
Fix Bug 460866 - SCM polling appears to hang Hudson
Lock order problem. Some paths are Queue lock then Project lock. Poll was Project lock then Queue lock. Fixed by adding an independent project delete lock.
-rw-r--r--hudson-core/src/main/java/hudson/model/AbstractItem.java48
-rw-r--r--hudson-core/src/main/java/hudson/scm/SCM.java31
2 files changed, 52 insertions, 27 deletions
diff --git a/hudson-core/src/main/java/hudson/model/AbstractItem.java b/hudson-core/src/main/java/hudson/model/AbstractItem.java
index a701a300..b76e8625 100644
--- a/hudson-core/src/main/java/hudson/model/AbstractItem.java
+++ b/hudson-core/src/main/java/hudson/model/AbstractItem.java
@@ -261,6 +261,7 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
public void onLoad(ItemGroup<? extends Item> parent, String name) throws IOException {
this.parent = parent;
doSetName(name);
+ deleteLock = new Object();
}
/**
@@ -381,25 +382,50 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
throw new ServletException(e);
}
}
+
+ private transient Object deleteLock = new Object();
+
+ /**
+ * Get delete lock. Used as follows:
+ *
+ * <pre>
+ * synchronized(project.getDeleteLock()) {
+ * if (!project.isDeleted()) {
+ * // do something with project root folder
+ * }
+ * }
+ * </pre>
+ * @return delete lock that can be used to prevent deletion while performing
+ * operations requiring access to item (job) folder. Should be obtained
+ * before any other lock/synchronized to avoid deadlock.
+ * @since 3.3.0
+ * @see #isDeleted
+ */
+ public Object getDeleteLock() {
+ return deleteLock;
+ }
/**
* Deletes this item.
*/
public void delete() throws IOException, InterruptedException {
final ItemGroup group = getParent();
- // Lock parent, and then 'this' before deleting.
- synchronized (group) {
- synchronized (this) {
- checkPermission(DELETE);
- performDelete();
+ // Obtain delete lock
+ synchronized (getDeleteLock()) {
+ // Lock parent, and then 'this' before deleting.
+ synchronized (group) {
+ synchronized (this) {
+ checkPermission(DELETE);
+ performDelete();
- try {
- invokeOnDeleted();
- } catch (AbstractMethodError e) {
- // ignore
- }
+ try {
+ invokeOnDeleted();
+ } catch (AbstractMethodError e) {
+ // ignore
+ }
- Hudson.getInstance().rebuildDependencyGraph();
+ Hudson.getInstance().rebuildDependencyGraph();
+ }
}
}
}
diff --git a/hudson-core/src/main/java/hudson/scm/SCM.java b/hudson-core/src/main/java/hudson/scm/SCM.java
index 5c0e941e..49c32bbe 100644
--- a/hudson-core/src/main/java/hudson/scm/SCM.java
+++ b/hudson-core/src/main/java/hudson/scm/SCM.java
@@ -359,26 +359,25 @@ public abstract class SCM implements Describable<SCM>, ExtensionPoint {
*/
public final PollingResult poll(AbstractProject<?, ?> project, Launcher launcher, FilePath workspace, TaskListener listener, SCMRevisionState baseline) throws IOException, InterruptedException {
// Ensure poll can't run during project delete.
- synchronized (project.getParent()) {
- synchronized (project) {
- if (!project.isDeleted()) {
- if (is1_346OrLater()) {
- // This is to work around HUDSON-5827 in a general way.
- // don't let the SCM.compareRemoteRevisionWith(...) see SCMRevisionState that it didn't produce.
- SCMRevisionState baseline2;
- if (baseline != SCMRevisionState.NONE) {
- baseline2 = baseline;
- } else {
- baseline2 = _calcRevisionsFromBuild(project.getLastBuild(), launcher, listener);
- }
-
- return _compareRemoteRevisionWith(project, launcher, workspace, listener, baseline2);
+ // Fix Bug 460866 - SCM polling appears to hang Hudson
+ synchronized (project.getDeleteLock()) {
+ if (!project.isDeleted()) {
+ if (is1_346OrLater()) {
+ // This is to work around HUDSON-5827 in a general way.
+ // don't let the SCM.compareRemoteRevisionWith(...) see SCMRevisionState that it didn't produce.
+ SCMRevisionState baseline2;
+ if (baseline != SCMRevisionState.NONE) {
+ baseline2 = baseline;
} else {
- return pollChanges(project, launcher, workspace, listener) ? PollingResult.SIGNIFICANT : PollingResult.NO_CHANGES;
+ baseline2 = _calcRevisionsFromBuild(project.getLastBuild(), launcher, listener);
}
+
+ return _compareRemoteRevisionWith(project, launcher, workspace, listener, baseline2);
} else {
- return PollingResult.NO_CHANGES;
+ return pollChanges(project, launcher, workspace, listener) ? PollingResult.SIGNIFICANT : PollingResult.NO_CHANGES;
}
+ } else {
+ return PollingResult.NO_CHANGES;
}
}
}

Back to the top