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 1ac15fe0ce1..07441e3e4bb 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 @@ -81,7 +81,8 @@ import org.eclipse.jetty.util.thread.Invocable; public class SslConnection extends AbstractConnection { private static final Logger LOG = Log.getLogger(SslConnection.class); - + private static final ThreadLocal __tryWriteAgain = new ThreadLocal<>(); + private final List handshakeListeners = new ArrayList<>(); private final ByteBufferPool _bufferPool; private final SSLEngine _sslEngine; @@ -95,7 +96,7 @@ public class SslConnection extends AbstractConnection private int _renegotiationLimit = -1; private boolean _closedOutbound; private boolean _allowMissingCloseMessage = true; - + private abstract class RunnableTask implements Runnable, Invocable { private final String _operation; @@ -506,11 +507,12 @@ public class SslConnection extends AbstractConnection } else { + // TODO This should not be required and we should be able to do all retries within flush // We can get here because the WriteFlusher might not see progress // when it has just flushed the encrypted data, but not consumed anymore // of the application buffers. This is mostly avoided by another iteration - // within DecryptedEndPoint flush(), but I cannot convince myself that - // this is never ever the case. + // within DecryptedEndPoint flush(), but this still occurs sometime on some + // tests on some systems??? More investigation is needed! try_again = true; } } @@ -526,12 +528,35 @@ public class SslConnection extends AbstractConnection { // don't bother writing, just notify of close getWriteFlusher().onClose(); + return; + } + + // TODO this ugly recursion protection is only needed until we remove the try again + // logic from this method and make flush do the try again. + Boolean tryWriteAgain = __tryWriteAgain.get(); + if (tryWriteAgain==null) + { + try + { + // Keep running complete write until + __tryWriteAgain.set(Boolean.FALSE); + do + { + _runCompleteWrite.run(); + } + while (Boolean.TRUE.equals(__tryWriteAgain.get())); + } + finally + { + __tryWriteAgain.remove(); + } } else { - // Try again - _runCompleteWrite.run(); + // Don't recurse but get top caller to iterate + __tryWriteAgain.set(Boolean.TRUE); } + } }