diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Connection.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Connection.java index a414dff9d9b..cd26737ebfb 100644 --- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Connection.java +++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Connection.java @@ -108,11 +108,11 @@ public class HTTP2Connection extends AbstractConnection implements WriteFlusher. } @Override - public void onClose() + public void onClose(Throwable cause) { if (LOG.isDebugEnabled()) LOG.debug("HTTP2 Close {} ", this); - super.onClose(); + super.onClose(cause); LifeCycle.stop(strategy); } diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java index d0e5abd6153..d859c34619f 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java @@ -215,11 +215,15 @@ public abstract class AbstractConnection implements Connection } @Override - public void onClose() + public void onClose(Throwable cause) { if (LOG.isDebugEnabled()) - LOG.debug("onClose {}",this); - + { + if (cause==null) + LOG.debug("onClose {}", this); + else + LOG.debug("onClose " + this, cause); + } for (Listener listener : _listeners) onClosed(listener); } diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java index d1cda54bdef..262e402212c 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java @@ -232,13 +232,6 @@ public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint { } - protected void onClose(Throwable failure) - { - super.onClose(); - _writeFlusher.onFail(failure); - _fillInterest.onFail(failure); - } - @Override public boolean isOutputShutdown() { @@ -347,13 +340,28 @@ public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint } @Override - public void onClose() + public final void onClose() + { + onClose(null); + } + + @Override + public void onClose(Throwable failure) { super.onClose(); - _writeFlusher.onClose(); - _fillInterest.onClose(); + if (failure==null) + { + _writeFlusher.onClose(); + _fillInterest.onClose(); + } + else + { + _writeFlusher.onFail(failure); + _fillInterest.onFail(failure); + } } + @Override public void fillInterested(Callback callback) { @@ -427,7 +435,7 @@ public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint ByteBuffer prefilled = (old_connection instanceof Connection.UpgradeFrom) ? ((Connection.UpgradeFrom)old_connection).onUpgradeFrom() : null; - old_connection.onClose(); + old_connection.onClose(null); old_connection.getEndPoint().setConnection(newConnection); if (LOG.isDebugEnabled()) diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ChannelEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ChannelEndPoint.java index 84a08b3f6bb..117bb49fea9 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/ChannelEndPoint.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ChannelEndPoint.java @@ -208,16 +208,16 @@ public abstract class ChannelEndPoint extends AbstractEndPoint implements Manage } @Override - public void onClose() + public void onClose(Throwable cause) { try { - super.onClose(); + super.onClose(cause); } finally { if (_selector!=null) - _selector.destroyEndPoint(this); + _selector.destroyEndPoint(this, cause); } } diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java index 76828bc53e5..50ca3833ec1 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java @@ -56,8 +56,9 @@ public interface Connection extends Closeable /** *

Callback method invoked when this connection is closed.

*

Creators of the connection implementation are responsible for calling this method.

+ * @param cause The cause of the close or null for a normal close */ - public void onClose(); + public void onClose(Throwable cause); /** * @return the {@link EndPoint} associated with this Connection. diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/EndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/EndPoint.java index 61e16c95c4d..b5cec4ce63f 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/EndPoint.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/EndPoint.java @@ -150,7 +150,16 @@ public interface EndPoint extends Closeable * Close any backing stream associated with the endpoint */ @Override - void close(); + default void close() + { + close (null); + } + + /** + * Close any backing stream associated with the endpoint, passing a cause + * @param cause the reason for the close or null + */ + void close(Throwable cause); /** * Fill the passed buffer with data from this endpoint. The bytes are appended to any @@ -248,15 +257,16 @@ public interface EndPoint extends Closeable /** *

Callback method invoked when this {@link EndPoint} is opened.

- * @see #onClose() + * @see #onClose(Throwable) */ void onOpen(); /** *

Callback method invoked when this {@link EndPoint} is close.

+ * @param cause The reason for the close, or null if a normal close. * @see #onOpen() */ - void onClose(); + void onClose(Throwable cause); /** Is the endpoint optimized for DirectBuffer usage * @return True if direct buffers can be used optimally. diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ManagedSelector.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ManagedSelector.java index 1dca5816e75..4594b5a9299 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/ManagedSelector.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ManagedSelector.java @@ -270,13 +270,13 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable LOG.debug("Created {}", endPoint); } - public void destroyEndPoint(final EndPoint endPoint) + public void destroyEndPoint(final EndPoint endPoint, Throwable cause) { // Waking up the selector is necessary to clean the // cancelled-key set and tell the TCP stack that the // socket is closed (so that senders receive RST). wakeup(); - execute(new DestroyEndPoint(endPoint)); + execute(new DestroyEndPoint(endPoint, cause)); } private int getActionSize() @@ -942,10 +942,12 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable private class DestroyEndPoint implements Runnable, Closeable { private final EndPoint endPoint; + private final Throwable cause; - public DestroyEndPoint(EndPoint endPoint) + public DestroyEndPoint(EndPoint endPoint, Throwable cause) { this.endPoint = endPoint; + this.cause = cause; } @Override @@ -955,7 +957,7 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable LOG.debug("Destroyed {}", endPoint); Connection connection = endPoint.getConnection(); if (connection != null) - _selectorManager.connectionClosed(connection); + _selectorManager.connectionClosed(connection, cause); _selectorManager.endPointClosed(endPoint); } diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/NetworkTrafficSelectChannelEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/NetworkTrafficSelectChannelEndPoint.java index 8e347fca9a9..5fbaca308d3 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/NetworkTrafficSelectChannelEndPoint.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/NetworkTrafficSelectChannelEndPoint.java @@ -94,9 +94,9 @@ public class NetworkTrafficSelectChannelEndPoint extends SocketChannelEndPoint } @Override - public void onClose() + public void onClose(Throwable cause) { - super.onClose(); + super.onClose(cause); if (listeners != null && !listeners.isEmpty()) { for (NetworkTrafficListener listener : listeners) diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java b/jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java index b35ed0f1e4c..25ffb3b5d3b 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java @@ -337,12 +337,13 @@ public abstract class SelectorManager extends ContainerLifeCycle implements Dump *

Callback method invoked when a connection is closed.

* * @param connection the connection just closed + * @param cause the cause of the close or null for normal close */ - public void connectionClosed(Connection connection) + public void connectionClosed(Connection connection, Throwable cause) { try { - connection.onClose(); + connection.onClose(cause); } catch (Throwable x) { diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java index bc2431d8ecc..15518193881 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java @@ -284,10 +284,10 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr } @Override - public void onClose() + public void onClose(Throwable cause) { - _decryptedEndPoint.getConnection().onClose(); - super.onClose(); + _decryptedEndPoint.getConnection().onClose(cause); + super.onClose(cause); } @Override diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/SslConnectionTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/SslConnectionTest.java index 9bc59170b11..dfbb26e0f0f 100644 --- a/jetty-io/src/test/java/org/eclipse/jetty/io/SslConnectionTest.java +++ b/jetty-io/src/test/java/org/eclipse/jetty/io/SslConnectionTest.java @@ -203,9 +203,9 @@ public class SslConnectionTest } @Override - public void onClose() + public void onClose(Throwable cause) { - super.onClose(); + super.onClose(cause); } @Override diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java index 91575cfe9bd..7c0e4185e51 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java @@ -511,10 +511,13 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http } @Override - public void onClose() + public void onClose(Throwable cause) { - _sendCallback.close(); - super.onClose(); + if (cause==null) + _sendCallback.close(); + else + _sendCallback.failed(cause); + super.onClose(cause); } @Override diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java index c1fb7ef325c..36c58bb9580 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java @@ -324,13 +324,13 @@ public class LocalConnector extends AbstractConnector } @Override - public void onClose() + public void onClose(Throwable cause) { Connection connection = getConnection(); if (connection!=null) - connection.onClose(); + connection.onClose(cause); LocalConnector.this.onEndPointClosed(this); - super.onClose(); + super.onClose(cause); _closed.countDown(); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ProxyConnectionFactory.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ProxyConnectionFactory.java index 49d1b3542b0..faccd4d87ec 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ProxyConnectionFactory.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ProxyConnectionFactory.java @@ -661,9 +661,9 @@ public class ProxyConnectionFactory extends AbstractConnectionFactory } @Override - public void close() + public void close(Throwable cause) { - _endp.close(); + _endp.close(cause); } @Override @@ -739,9 +739,9 @@ public class ProxyConnectionFactory extends AbstractConnectionFactory } @Override - public void onClose() + public void onClose(Throwable cause) { - _endp.onClose(); + _endp.onClose(cause); } @Override diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/internal/FrameFlusher.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/internal/FrameFlusher.java index ad4da0bc9ee..a437263538a 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/internal/FrameFlusher.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/internal/FrameFlusher.java @@ -41,6 +41,7 @@ public class FrameFlusher extends IteratingCallback { public static final Frame FLUSH_FRAME = new Frame(OpCode.BINARY); private static final Logger LOG = Log.getLogger(FrameFlusher.class); + private static final Throwable CLOSED_CHANNEL = new ClosedChannelException(); private final ByteBufferPool bufferPool; private final EndPoint endPoint; @@ -95,14 +96,11 @@ public class FrameFlusher extends IteratingCallback return failure==null; } - public void onClose(Throwable t) + public void onClose(Throwable cause) { - if (t == null) - t = new ClosedChannelException(); - synchronized (this) { - closedCause = t; + closedCause = cause == null ? CLOSED_CHANNEL : cause; } iterate(); @@ -265,10 +263,7 @@ public class FrameFlusher extends IteratingCallback entry.release(); } entries.clear(); - if (endPoint instanceof AbstractEndPoint) - ((AbstractEndPoint)endPoint).close(failure); - else - endPoint.close(); + endPoint.close(failure); } private void releaseAggregate() diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/internal/WebSocketConnection.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/internal/WebSocketConnection.java index 1879e386dad..87a66eef044 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/internal/WebSocketConnection.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/internal/WebSocketConnection.java @@ -163,19 +163,15 @@ public class WebSocketConnection extends AbstractConnection implements Connectio * Not related to WebSocket close handshake. */ @Override - public void onClose() + public void onClose(Throwable cause) { if (LOG.isDebugEnabled()) LOG.debug("onClose() of physical connection"); - Throwable t = new ClosedChannelException(); - if (!channel.isClosed()) channel.onEof(); - - flusher.onClose(t); - - super.onClose(); + flusher.onClose(cause); + super.onClose(cause); }