提交 07fb00e0 编写于 作者: S Stephen Connolly

If you are synchronizing on something to access a volatile, then you are doing something wrong

- Yet more interrupting bad patterns, especially where we expect the node monitor to take up to 30 seconds to complete if an async variety
上级 68f62226
......@@ -108,12 +108,5 @@ public abstract class AbstractAsyncNodeMonitorDescriptor<T> extends AbstractNode
return data;
}
/**
* Controls the time out of monitoring.
*/
protected long getMonitoringTimeOut() {
return TimeUnit.SECONDS.toMillis(30);
}
private static final Logger LOGGER = Logger.getLogger(AbstractAsyncNodeMonitorDescriptor.class.getName());
}
......@@ -26,6 +26,7 @@ package hudson.node_monitors;
import hudson.Util;
import hudson.model.Computer;
import hudson.model.Descriptor;
import hudson.model.Run;
import jenkins.model.Jenkins;
import hudson.model.ComputerSet;
import hudson.model.AdministrativeMonitor;
......@@ -33,6 +34,7 @@ import hudson.triggers.SafeTimerTask;
import hudson.slaves.OfflineCause;
import jenkins.util.Timer;
import javax.annotation.concurrent.GuardedBy;
import java.io.IOException;
import java.util.Collections;
import java.util.Date;
......@@ -105,7 +107,14 @@ public abstract class AbstractNodeMonitorDescriptor<T> extends Descriptor<NodeMo
/**
* Represents the update activity in progress.
*/
private transient volatile Record inProgress = null;
@GuardedBy("this")
private transient Record inProgress = null;
/**
* Represents when an update activity was last started.
*/
@GuardedBy("this")
private transient long inProgressStarted = Long.MIN_VALUE;
/**
* Performs monitoring of the given computer object.
......@@ -171,9 +180,8 @@ public abstract class AbstractNodeMonitorDescriptor<T> extends Descriptor<NodeMo
/**
* Is the monitoring activity currently in progress?
*/
private boolean isInProgress() {
Record r = inProgress; // capture for atomicity
return r!=null && r.isAlive();
private synchronized boolean isInProgress() {
return inProgress !=null && inProgress.isAlive();
}
/**
......@@ -242,10 +250,32 @@ public abstract class AbstractNodeMonitorDescriptor<T> extends Descriptor<NodeMo
/**
* @see NodeMonitor#triggerUpdate()
*/
/*package*/ Thread triggerUpdate() {
Record t = new Record();
/*package*/ synchronized Thread triggerUpdate() {
if (inProgress != null) {
if (System.currentTimeMillis() > inProgressStarted + getMonitoringTimeOut() + 1000) {
// maybe it got stuck?
LOGGER.log(Level.WARNING, "Previous {0} monitoring activity still in progress. Interrupting",
getDisplayName());
inProgress.interrupt();
inProgress = null; // we interrupted the old one so it's now dead to us.
} else {
// return the in progress
return inProgress;
}
}
final Record t = new Record();
t.start();
return t;
// only store the new thread if we started it
inProgress = t;
inProgressStarted = System.currentTimeMillis();
return inProgress;
}
/**
* Controls the time out of monitoring.
*/
protected long getMonitoringTimeOut() {
return TimeUnit.SECONDS.toMillis(30);
}
/**
......@@ -262,14 +292,6 @@ public abstract class AbstractNodeMonitorDescriptor<T> extends Descriptor<NodeMo
public Record() {
super("Monitoring thread for "+getDisplayName()+" started on "+new Date());
synchronized(AbstractNodeMonitorDescriptor.this) {
if(inProgress!=null) {
// maybe it got stuck?
LOGGER.log(Level.WARNING, "Previous {0} monitoring activity still in progress. Interrupting", getDisplayName());
inProgress.interrupt();
}
inProgress = this;
}
}
@Override
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册