提交 abbde774 编写于 作者: O Oleg Nenashev

Added missing null checks for Computer::getNode(), SlaveComputer::getNode()...

Added missing null checks for Computer::getNode(), SlaveComputer::getNode() and AbstractBuild::getCurrentNode()
Signed-off-by: NOleg Nenashev <o.v.nenashev@gmail.com>

Conflicts:
	core/src/main/java/hudson/model/AbstractBuild.java
上级 d3cbc252
......@@ -122,6 +122,9 @@ public class InstallToolCommand extends CLICommand {
throw new AbortException(b.getFullDisplayName()+" is not building");
Node node = exec.getOwner().getNode();
if (node == null) {
throw new AbortException("The node " + exec.getOwner().getDisplayName() + " has been deleted");
}
t = t.translate(node, EnvVars.getRemote(checkChannel()), new StreamTaskListener(stderr));
stdout.println(t.getHome());
......
......@@ -84,10 +84,11 @@ import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import org.kohsuke.stapler.interceptor.RequirePOST;
import static java.util.logging.Level.WARNING;
import javax.annotation.Nonnull;
import jenkins.model.lazy.BuildReference;
import jenkins.model.lazy.LazyBuildMixIn;
......@@ -436,6 +437,7 @@ public abstract class AbstractBuild<P extends AbstractProject<P,R>,R extends Abs
/**
* Returns the current {@link Node} on which we are building.
* @return Returns the current {@link Node} or null if current thread is not an executor.
* @throws IllegalStateException if that cannot be determined
*/
protected final @Nonnull Node getCurrentNode() throws IllegalStateException {
......@@ -477,8 +479,12 @@ public abstract class AbstractBuild<P extends AbstractProject<P,R>,R extends Abs
return wsl.allocate(n.getWorkspaceFor((TopLevelItem)getProject()), getBuild());
}
public Result run(BuildListener listener) throws Exception {
Node node = getCurrentNode();
public Result run(@Nonnull BuildListener listener) throws Exception {
final Node node = getCurrentNode();
if (node == null) {
throw new AbortException(Messages.AbstractBuild_NoExecutorError());
}
assert builtOn==null;
builtOn = node.getNodeName();
hudsonVersion = Jenkins.VERSION;
......@@ -566,8 +572,13 @@ public abstract class AbstractBuild<P extends AbstractProject<P,R>,R extends Abs
* @param listener
* Always non-null. Connected to the main build output.
*/
protected Launcher createLauncher(BuildListener listener) throws IOException, InterruptedException {
Launcher l = getCurrentNode().createLauncher(listener);
@Nonnull
protected Launcher createLauncher(@Nonnull BuildListener listener) throws IOException, InterruptedException {
final Node currentNode = getCurrentNode();
if (currentNode == null) {
throw new AbortException(Messages.AbstractBuild_NoExecutorError());
}
Launcher l = currentNode.createLauncher(listener);
if (project instanceof BuildableItemWithBuildWrappers) {
BuildableItemWithBuildWrappers biwbw = (BuildableItemWithBuildWrappers) project;
......@@ -591,7 +602,7 @@ public abstract class AbstractBuild<P extends AbstractProject<P,R>,R extends Abs
}
}
for (NodeProperty nodeProperty: Computer.currentComputer().getNode().getNodeProperties()) {
for (NodeProperty nodeProperty: currentNode.getNodeProperties()) {
Environment environment = nodeProperty.setUp(AbstractBuild.this, l, listener);
if (environment != null) {
buildEnvironments.add(environment);
......
......@@ -165,9 +165,10 @@ public abstract class AbstractCIBase extends Node implements ItemGroup<TopLevelI
synchronized(updateComputerLock) {// just so that we don't have two code updating computer list at the same time
Map<String,Computer> byName = new HashMap<String,Computer>();
for (Computer c : computers.values()) {
if(c.getNode()==null)
Node node = c.getNode();
if (node == null)
continue; // this computer is gone
byName.put(c.getNode().getNodeName(),c);
byName.put(node.getNodeName(),c);
}
Set<Computer> old = new HashSet<Computer>(computers.values());
......
......@@ -1196,7 +1196,11 @@ public /*transient*/ abstract class Computer extends Actionable implements Acces
// read
checkPermission(EXTENDED_READ);
rsp.setContentType("application/xml");
Jenkins.XSTREAM2.toXMLUTF8(getNode(), rsp.getOutputStream());
Node node = getNode();
if (node == null) {
throw new ServletException("No such node " + nodeName);
}
Jenkins.XSTREAM2.toXMLUTF8(node, rsp.getOutputStream());
return;
}
if (req.getMethod().equals("POST")) {
......@@ -1218,7 +1222,8 @@ public /*transient*/ abstract class Computer extends Actionable implements Acces
// replace the old Node object by the new one
synchronized (app) {
List<Node> nodes = new ArrayList<Node>(app.getNodes());
int i = nodes.indexOf(getNode());
Node node = getNode();
int i = (node != null) ? nodes.indexOf(node) : -1;
if(i<0) {
throw new IOException("This slave appears to be removed while you were editing the configuration");
}
......
......@@ -283,6 +283,7 @@ public class Queue extends ResourceController implements Saveable {
return workUnit == null && !executor.getOwner().isOffline() && executor.getOwner().isAcceptingTasks();
}
@CheckForNull
public Node getNode() {
return executor.getOwner().getNode();
}
......@@ -739,6 +740,8 @@ public class Queue extends ResourceController implements Saveable {
private void _getBuildableItems(Computer c, ItemList<BuildableItem> col, List<BuildableItem> result) {
Node node = c.getNode();
if (node == null) // Deleted computers cannot take build items...
return;
for (BuildableItem p : col.values()) {
if (node.canTake(p) == null)
result.add(p);
......
......@@ -26,6 +26,7 @@ package hudson.node_monitors;
import hudson.Extension;
import hudson.FilePath;
import hudson.model.Computer;
import hudson.model.Node;
import hudson.remoting.Callable;
import jenkins.model.Jenkins;
import hudson.node_monitors.DiskSpaceMonitorDescriptor.DiskSpace;
......@@ -66,7 +67,10 @@ public class DiskSpaceMonitor extends AbstractDiskSpaceMonitor {
@Override
protected Callable<DiskSpace, IOException> createCallable(Computer c) {
FilePath p = c.getNode().getRootPath();
Node node = c.getNode();
if (node == null) return null;
FilePath p = node.getRootPath();
if(p==null) return null;
return p.asCallableWith(new GetUsableSpace());
......
......@@ -27,6 +27,7 @@ import hudson.Extension;
import hudson.FilePath;
import hudson.FilePath.FileCallable;
import hudson.model.Computer;
import hudson.model.Node;
import hudson.remoting.Callable;
import jenkins.model.Jenkins;
import hudson.node_monitors.DiskSpaceMonitorDescriptor.DiskSpace;
......@@ -67,7 +68,10 @@ public class TemporarySpaceMonitor extends AbstractDiskSpaceMonitor {
@Override
protected Callable<DiskSpace,IOException> createCallable(Computer c) {
FilePath p = c.getNode().getRootPath();
Node node = c.getNode();
if (node == null) return null;
FilePath p = node.getRootPath();
if(p==null) return null;
return p.asCallableWith(new GetTempSpace());
......
......@@ -29,6 +29,7 @@ import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.HttpResponses;
import java.io.IOException;
import javax.annotation.CheckForNull;
/**
* Partial implementation of {@link Computer} to be used in conjunction with
......@@ -42,6 +43,7 @@ public class AbstractCloudComputer<T extends AbstractCloudSlave> extends SlaveCo
super(slave);
}
@CheckForNull
@Override
public T getNode() {
return (T) super.getNode();
......@@ -54,7 +56,10 @@ public class AbstractCloudComputer<T extends AbstractCloudSlave> extends SlaveCo
public HttpResponse doDoDelete() throws IOException {
checkPermission(DELETE);
try {
getNode().terminate();
T node = getNode();
if (node != null) { // Node need to terminate nodes again
node.terminate();
}
return new HttpRedirect("..");
} catch (InterruptedException e) {
return HttpResponses.error(500,e);
......
......@@ -23,10 +23,12 @@
*/
package hudson.slaves;
import hudson.AbortException;
import hudson.EnvVars;
import hudson.Util;
import hudson.Extension;
import hudson.model.Descriptor;
import hudson.model.Slave;
import jenkins.model.Jenkins;
import hudson.model.TaskListener;
import hudson.remoting.Channel;
......@@ -87,6 +89,11 @@ public class CommandLauncher extends ComputerLauncher {
EnvVars _cookie = null;
Process _proc = null;
try {
Slave node = computer.getNode();
if (node == null) {
throw new AbortException("Cannot launch commands on deleted nodes");
}
listener.getLogger().println(hudson.model.Messages.Slave_Launching(getTimestamp()));
if(getCommand().trim().length()==0) {
listener.getLogger().println(Messages.CommandLauncher_NoLaunchCommand());
......@@ -96,8 +103,8 @@ public class CommandLauncher extends ComputerLauncher {
ProcessBuilder pb = new ProcessBuilder(Util.tokenize(getCommand()));
final EnvVars cookie = _cookie = EnvVars.createCookie();
pb.environment().putAll(cookie);
pb.environment().put("WORKSPACE", computer.getNode().getRemoteFS()); //path for local slave log
pb.environment().putAll(cookie);
pb.environment().put("WORKSPACE", node.getRemoteFS()); //path for local slave log
{// system defined variables
String rootUrl = Jenkins.getInstance().getRootUrl();
......
......@@ -24,6 +24,7 @@
package hudson.slaves;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.model.Node;
import hudson.model.EnvironmentSpecific;
import hudson.model.TaskListener;
......@@ -44,5 +45,5 @@ public interface NodeSpecific<T extends NodeSpecific<T>> {
/**
* Returns a specialized copy of T for functioning in the given node.
*/
T forNode(Node node, TaskListener log) throws IOException, InterruptedException;
T forNode(@NonNull Node node, TaskListener log) throws IOException, InterruptedException;
}
......@@ -78,8 +78,11 @@ import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import javax.annotation.CheckForNull;
import jenkins.model.Jenkins;
import static hudson.slaves.SlaveComputer.LogHolder.*;
/**
* {@link Computer} for {@link Slave}s.
*
......@@ -168,6 +171,7 @@ public class SlaveComputer extends Computer {
return isUnix;
}
@CheckForNull
@Override
public Slave getNode() {
Node node = super.getNode();
......@@ -454,10 +458,15 @@ public class SlaveComputer extends Computer {
String defaultCharsetName = channel.call(new DetectDefaultCharset());
String remoteFs = getNode().getRemoteFS();
Slave node = getNode();
if (node == null) { // Node has been disabled/removed during the connection
throw new IOException("Node "+nodeName+" has been deleted during the channel setup");
}
String remoteFs = node.getRemoteFS();
if(_isUnix && !remoteFs.contains("/") && remoteFs.contains("\\"))
log.println("WARNING: "+remoteFs+" looks suspiciously like Windows path. Maybe you meant "+remoteFs.replace('\\','/')+"?");
FilePath root = new FilePath(channel,getNode().getRemoteFS());
FilePath root = new FilePath(channel,node.getRemoteFS());
// reference counting problem is known to happen, such as JENKINS-9017, and so as a preventive measure
// we pin the base classloader so that it'll never get GCed. When this classloader gets released,
......
......@@ -41,6 +41,8 @@ import java.util.List;
import com.thoughtworks.xstream.annotations.XStreamSerializable;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jenkins.model.Jenkins;
/**
......@@ -152,7 +154,7 @@ public abstract class ToolInstallation extends AbstractDescribableImpl<ToolInsta
* Performs a necessary variable/environment/context expansion.
*
* @param node
* Node that this tool is used in.
* Node that this tool is used in. Should not be null
* @param envs
* Set of environment variables to expand any references.
* @param listener
......@@ -163,7 +165,7 @@ public abstract class ToolInstallation extends AbstractDescribableImpl<ToolInsta
* @see EnvironmentSpecific
* @since 1.460
*/
public ToolInstallation translate(Node node, EnvVars envs, TaskListener listener) throws IOException, InterruptedException {
public ToolInstallation translate(@Nonnull Node node, EnvVars envs, TaskListener listener) throws IOException, InterruptedException {
ToolInstallation t = this;
if (t instanceof NodeSpecific) {
NodeSpecific n = (NodeSpecific) t;
......
......@@ -27,6 +27,7 @@ AbstractBuild.BuildingOnMaster=Building on master
AbstractBuild_Building=Building
AbstractBuild.BuildingInWorkspace=\ in workspace {0}
AbstractBuild.KeptBecause=This build is kept because of {0}.
AbstractBuild.NoExecutorError=Cannot run the build outside executor threads
AbstractItem.NoSuchJobExists=No such job \u2018{0}\u2019 exists. Perhaps you meant \u2018{1}\u2019?
AbstractItem.Pronoun=Item
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册