Skip to content
Permalink
Browse files

[JENKINS-39289] When a proxy fails, report what caused the channel to…

… go down

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 committed Oct 27, 2016
1 parent 9dc9317 commit 89a1774918d1e2adba41ae7ae4ba34f095dc2676
@@ -201,7 +201,7 @@
* 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.
@@ -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();
@@ -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
@@ -898,7 +899,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();
}
@@ -1701,17 +1702,29 @@ public static void dumpDiagnosticsForAll(@Nonnull PrintWriter w) {
* @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;
}

@@ -1724,12 +1737,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;
}

/**
@@ -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;
}

/**

0 comments on commit 89a1774

Please sign in to comment.
You can’t perform that action at this time.