Skip to content

Commit

Permalink
[JENKINS-39289] When a proxy fails, report what caused the channel to…
Browse files Browse the repository at this point in the history
… go down (#128)

Today, this requires out of bound knowledge about which connection the
proxy was representing, then use other means to figure out why it has
failed.

This exception chaining shortens that step and makes it easy to find the
cause as to why the channel was shut down.
  • Loading branch information
kohsuke authored and oleg-nenashev committed Nov 4, 2016
1 parent 46c72a5 commit 0d8a2af
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 9 deletions.
39 changes: 34 additions & 5 deletions src/main/java/hudson/remoting/Channel.java
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ public class Channel implements VirtualChannel, IChannel, Closeable {
* termination and simplify the circles into chains which can then be collected easily by the garbage collector.
* @since FIXME after merge
*/
private final Ref reference = new Ref(this);
private final Ref reference;

/**
* Registered listeners.
Expand Down Expand Up @@ -491,6 +491,7 @@ public Channel(String name, ExecutorService exec, CommandTransport transport, bo
*/
protected Channel(ChannelBuilder settings, CommandTransport transport) throws IOException {
this.name = settings.getName();
this.reference = new Ref(this);
this.executor = new InterceptingExecutorService(settings.getExecutors(),decorators);
this.arbitraryCallableAllowed = settings.isArbitraryCallableAllowed();
this.remoteClassLoadingAllowed = settings.isRemoteClassLoadingAllowed();
Expand Down Expand Up @@ -537,7 +538,7 @@ public void terminate(IOException e) {
}

/**
* Gets the {@link Ref} for this {@link Channel}. The {@link Ref} will be {@linkplain Ref#clear()}ed when
* Gets the {@link Ref} for this {@link Channel}. The {@link Ref} will be {@linkplain Ref#clear(Exception)}ed when
* the channel is terminated in order to break any complex object cycles.
* @return the {@link Ref} for this {@link Channel}
* @since FIXME after merge
Expand Down Expand Up @@ -896,7 +897,7 @@ public void terminate(IOException e) {
}
exportedObjects.abort(e);
// break any object cycles into simple chains to simplify work for the garbage collector
reference.clear();
reference.clear(e);
} finally {
notifyAll();
}
Expand Down Expand Up @@ -1703,17 +1704,29 @@ protected int[] initialValue() {
* @see #reference
*/
/*package*/ static final class Ref {
/**
* @see {@link Channel#getName()}
*/
@Nonnull
private final String name;

/**
* The channel.
*/
@CheckForNull
private Channel channel;

/**
* If the channel is cleared, retain the reason channel was closed to assist diagnostics.
*/
private Exception cause;

/**
* Constructor.
* @param channel the {@link Channel}.
*/
private Ref(@CheckForNull Channel channel) {
this.name = channel.getName();
this.channel = channel;
}

Expand All @@ -1726,12 +1739,28 @@ public Channel channel() {
return channel;
}

/**
* If the channel is null, return the cause of the channel termination.
*/
public Exception cause() {
return cause;
}

/**
* @see Channel#getName()
*/
@Nonnull
public String name() {
return name;
}

/**
* Clears the {@link #channel} to signify that the {@link Channel} has been closed and break any complex
* object cycles that might prevent the full garbage collection of the channel's associated object tree.
*/
public void clear() {
channel = null;
public void clear(Exception cause) {
this.channel = null;
this.cause = cause;
}

/**
Expand Down
12 changes: 8 additions & 4 deletions src/main/java/hudson/remoting/RemoteInvocationHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,15 @@ private Channel channel() {
*/
@Nonnull
private Channel channelOrFail() throws IOException {
final Channel channel = channel();
if (channel == null) {
throw new IOException("Backing channel is disconnected.");
final Ref ch = this.channel;
if (ch == null) {
throw new IOException("Not connected to any channel");
}
Channel c = ch.channel();
if (c == null) {
throw new IOException("Backing channel '"+ch.name()+"' is disconnected.",ch.cause());
}
return channel;
return c;
}

/**
Expand Down

0 comments on commit 0d8a2af

Please sign in to comment.