Skip to content

Commit

Permalink
[FIXED JENKINS-24110] - Explicitly handle null Executables in hudson.…
Browse files Browse the repository at this point in the history
…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: Oleg Nenashev <o.v.nenashev@gmail.com>
  • Loading branch information
oleg-nenashev committed Aug 18, 2014
1 parent bc6254b commit 128344d
Show file tree
Hide file tree
Showing 7 changed files with 22 additions and 7 deletions.
2 changes: 1 addition & 1 deletion core/src/main/java/hudson/model/AbstractProject.java
Expand Up @@ -1185,7 +1185,7 @@ public List<SubTask> getSubTasks() {
return r;
}

public R createExecutable() throws IOException {
public @CheckForNull R createExecutable() throws IOException {
if(isDisabled()) return null;
return newBuild();
}
Expand Down
7 changes: 7 additions & 0 deletions core/src/main/java/hudson/model/Executor.java
Expand Up @@ -220,6 +220,13 @@ public void run() {
try {
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) {
for (Action action: workUnit.context.actions) {
((Actionable) executable).addAction(action);
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/hudson/model/Queue.java
Expand Up @@ -1879,7 +1879,7 @@ public CauseOfBlockage getCauseOfBlockage() {
* the primary executable (such as {@link AbstractBuild}) that created out of it.
*/
@Exported
public Executable getExecutable() {
public @CheckForNull Executable getExecutable() {
return outcome!=null ? outcome.getPrimaryWorkUnit().getExecutable() : null;
}

Expand Down
3 changes: 2 additions & 1 deletion core/src/main/java/hudson/model/ResourceController.java
Expand Up @@ -30,6 +30,7 @@
import java.util.AbstractCollection;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.annotation.Nonnull;

/**
* Controls mutual exclusion of {@link ResourceList}.
Expand Down Expand Up @@ -73,7 +74,7 @@ public int size() {
* @throws InterruptedException
* 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();
synchronized(this) {
while(inUse.isCollidingWith(resources))
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/java/hudson/model/queue/QueueTaskFilter.java
Expand Up @@ -33,6 +33,7 @@

import java.io.IOException;
import java.util.Collection;
import javax.annotation.CheckForNull;

/**
* Base class for defining filter {@link hudson.model.Queue.Task}.
Expand Down Expand Up @@ -79,7 +80,7 @@ public long getEstimatedDuration() {
return base.getEstimatedDuration();
}

public Executable createExecutable() throws IOException {
public @CheckForNull Executable createExecutable() throws IOException {
return base.createExecutable();
}

Expand Down
7 changes: 6 additions & 1 deletion core/src/main/java/hudson/model/queue/SubTask.java
Expand Up @@ -23,6 +23,7 @@
*/
package hudson.model.queue;

import hudson.model.AbstractProject;
import hudson.model.Executor;
import hudson.model.Label;
import hudson.model.Node;
Expand All @@ -32,6 +33,7 @@

import javax.annotation.Nonnull;
import java.io.IOException;
import javax.annotation.CheckForNull;

/**
* A component of {@link Task} that represents a computation carried out by a single {@link Executor}.
Expand Down Expand Up @@ -70,8 +72,11 @@ public interface SubTask extends ResourceActivity {

/**
* 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.
Expand Down
5 changes: 3 additions & 2 deletions core/src/main/java/hudson/model/queue/WorkUnit.java
Expand Up @@ -27,6 +27,7 @@
import hudson.model.Queue;
import hudson.model.Queue.Executable;
import hudson.model.Queue.Task;
import javax.annotation.CheckForNull;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.export.ExportedBean;
Expand Down Expand Up @@ -63,11 +64,11 @@ public final class WorkUnit {
* {@link Executor#getCurrentWorkUnit()} and {@link WorkUnit#getExecutor()}
* form a bi-directional reachability between them.
*/
public Executor getExecutor() {
public @CheckForNull Executor getExecutor() {
return executor;
}

public void setExecutor(Executor e) {
public void setExecutor(@CheckForNull Executor e) {
executor = e;
}

Expand Down

0 comments on commit 128344d

Please sign in to comment.