提交 128344dd 编写于 作者: O Oleg Nenashev

[FIXED JENKINS-24110] - Explicitly handle null Executables in hudson.model.Executor

This change improves the handling of errors in hudson.model.Executor, which cause issues like JENKINS-18164.
The change also introduces several annotations in order to prevent further issues.
Signed-off-by: NOleg Nenashev <o.v.nenashev@gmail.com>
上级 bc6254b2
...@@ -1185,7 +1185,7 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A ...@@ -1185,7 +1185,7 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A
return r; return r;
} }
public R createExecutable() throws IOException { public @CheckForNull R createExecutable() throws IOException {
if(isDisabled()) return null; if(isDisabled()) return null;
return newBuild(); return newBuild();
} }
......
...@@ -220,6 +220,13 @@ public class Executor extends Thread implements ModelObject { ...@@ -220,6 +220,13 @@ public class Executor extends Thread implements ModelObject {
try { try {
workUnit.context.synchronizeStart(); workUnit.context.synchronizeStart();
// this code handles the behavior of null Executables returned
// by tasks. In such case Jenkins starts the workUnit in order
// to report results to console outputs.
if (executable == null) {
throw new Error("The null Executable has been created for "+workUnit+". The task cannot be executed");
}
if (executable instanceof Actionable) { if (executable instanceof Actionable) {
for (Action action: workUnit.context.actions) { for (Action action: workUnit.context.actions) {
((Actionable) executable).addAction(action); ((Actionable) executable).addAction(action);
......
...@@ -1879,7 +1879,7 @@ public class Queue extends ResourceController implements Saveable { ...@@ -1879,7 +1879,7 @@ public class Queue extends ResourceController implements Saveable {
* the primary executable (such as {@link AbstractBuild}) that created out of it. * the primary executable (such as {@link AbstractBuild}) that created out of it.
*/ */
@Exported @Exported
public Executable getExecutable() { public @CheckForNull Executable getExecutable() {
return outcome!=null ? outcome.getPrimaryWorkUnit().getExecutable() : null; return outcome!=null ? outcome.getPrimaryWorkUnit().getExecutable() : null;
} }
......
...@@ -30,6 +30,7 @@ import java.util.Collection; ...@@ -30,6 +30,7 @@ import java.util.Collection;
import java.util.AbstractCollection; import java.util.AbstractCollection;
import java.util.Iterator; import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
import javax.annotation.Nonnull;
/** /**
* Controls mutual exclusion of {@link ResourceList}. * Controls mutual exclusion of {@link ResourceList}.
...@@ -73,7 +74,7 @@ public class ResourceController { ...@@ -73,7 +74,7 @@ public class ResourceController {
* @throws InterruptedException * @throws InterruptedException
* the thread can be interrupted while waiting for the available resources. * the thread can be interrupted while waiting for the available resources.
*/ */
public void execute( Runnable task, ResourceActivity activity ) throws InterruptedException { public void execute(@Nonnull Runnable task, ResourceActivity activity ) throws InterruptedException {
ResourceList resources = activity.getResourceList(); ResourceList resources = activity.getResourceList();
synchronized(this) { synchronized(this) {
while(inUse.isCollidingWith(resources)) while(inUse.isCollidingWith(resources))
......
...@@ -33,6 +33,7 @@ import hudson.model.ResourceList; ...@@ -33,6 +33,7 @@ import hudson.model.ResourceList;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import javax.annotation.CheckForNull;
/** /**
* Base class for defining filter {@link hudson.model.Queue.Task}. * Base class for defining filter {@link hudson.model.Queue.Task}.
...@@ -79,7 +80,7 @@ public abstract class QueueTaskFilter implements Queue.Task { ...@@ -79,7 +80,7 @@ public abstract class QueueTaskFilter implements Queue.Task {
return base.getEstimatedDuration(); return base.getEstimatedDuration();
} }
public Executable createExecutable() throws IOException { public @CheckForNull Executable createExecutable() throws IOException {
return base.createExecutable(); return base.createExecutable();
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
*/ */
package hudson.model.queue; package hudson.model.queue;
import hudson.model.AbstractProject;
import hudson.model.Executor; import hudson.model.Executor;
import hudson.model.Label; import hudson.model.Label;
import hudson.model.Node; import hudson.model.Node;
...@@ -32,6 +33,7 @@ import hudson.model.ResourceActivity; ...@@ -32,6 +33,7 @@ import hudson.model.ResourceActivity;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.io.IOException; import java.io.IOException;
import javax.annotation.CheckForNull;
/** /**
* A component of {@link Task} that represents a computation carried out by a single {@link Executor}. * A component of {@link Task} that represents a computation carried out by a single {@link Executor}.
...@@ -70,8 +72,11 @@ public interface SubTask extends ResourceActivity { ...@@ -70,8 +72,11 @@ public interface SubTask extends ResourceActivity {
/** /**
* Creates {@link Executable}, which performs the actual execution of the task. * Creates {@link Executable}, which performs the actual execution of the task.
* @return {@link Executable} to be launched or null if the executable cannot be
* created (e.g. {@link AbstractProject} is disabled)
* @exception IOException {@link Executable} cannot be created
*/ */
Executable createExecutable() throws IOException; @CheckForNull Executable createExecutable() throws IOException;
/** /**
* Gets the {@link Task} that this subtask belongs to. * Gets the {@link Task} that this subtask belongs to.
......
...@@ -27,6 +27,7 @@ import hudson.model.Executor; ...@@ -27,6 +27,7 @@ import hudson.model.Executor;
import hudson.model.Queue; import hudson.model.Queue;
import hudson.model.Queue.Executable; import hudson.model.Queue.Executable;
import hudson.model.Queue.Task; import hudson.model.Queue.Task;
import javax.annotation.CheckForNull;
import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse; import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.export.ExportedBean; import org.kohsuke.stapler.export.ExportedBean;
...@@ -63,11 +64,11 @@ public final class WorkUnit { ...@@ -63,11 +64,11 @@ public final class WorkUnit {
* {@link Executor#getCurrentWorkUnit()} and {@link WorkUnit#getExecutor()} * {@link Executor#getCurrentWorkUnit()} and {@link WorkUnit#getExecutor()}
* form a bi-directional reachability between them. * form a bi-directional reachability between them.
*/ */
public Executor getExecutor() { public @CheckForNull Executor getExecutor() {
return executor; return executor;
} }
public void setExecutor(Executor e) { public void setExecutor(@CheckForNull Executor e) {
executor = e; executor = e;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册