diff --git a/remoting/src/main/java/hudson/remoting/Channel.java b/remoting/src/main/java/hudson/remoting/Channel.java index d79db7d40361e11f857815ed06ce81d5eaa04c0e..a28f89af95bc4d06a79a005f5ce30263fcdd87ca 100644 --- a/remoting/src/main/java/hudson/remoting/Channel.java +++ b/remoting/src/main/java/hudson/remoting/Channel.java @@ -631,6 +631,14 @@ public class Channel implements VirtualChannel, IChannel { wait(); } + /** + * If the receiving end of the channel is closed (that is, if we are guaranteed to receive nothing further), + * this method returns true. + */ + /*package*/ boolean isInClosed() { + return inClosed; + } + /** * Waits for this {@link Channel} to be closed down, but only up the given milliseconds. * diff --git a/remoting/src/main/java/hudson/remoting/Request.java b/remoting/src/main/java/hudson/remoting/Request.java index 115b2aa1e1d175fc9af714c3d5c4677afa1f0752..02c7619387856c2a65db284b099bc8360684b7d0 100644 --- a/remoting/src/main/java/hudson/remoting/Request.java +++ b/remoting/src/main/java/hudson/remoting/Request.java @@ -112,8 +112,15 @@ abstract class Request extends C final String name = t.getName(); try { t.setName(name+" / waiting for "+channel); - while(response==null) - wait(); // wait until the response arrives + while(response==null && !channel.isInClosed()) + // I don't know exactly when this can happen, as pendingCalls are cleaned up by Channel, + // but in production I've observed that in rare occasion it can block forever, even after a channel + // is gone. So be defensive against that. + wait(30*1000); // wait until the response arrives + + if (response==null) + // channel is closed and we still don't have a response + throw new RequestAbortedException(null); } catch (InterruptedException e) { // if we are cancelled, abort the remote computation, too channel.send(new Cancel(id));