diff --git a/core/src/main/java/io/undertow/UndertowLogger.java b/core/src/main/java/io/undertow/UndertowLogger.java index cdc66549e9..705062eb76 100644 --- a/core/src/main/java/io/undertow/UndertowLogger.java +++ b/core/src/main/java/io/undertow/UndertowLogger.java @@ -458,4 +458,8 @@ void nodeConfigCreated(URI connectionURI, String balancer, String domain, String @LogMessage(level = WARN) @Message(id = 5102, value = "Flushing waiting in a frame more than %s miliseconds. The framed channel will be forcibly closed.") void noFrameflushInTimeout(long timeoutMiliseconds); + + @LogMessage(level = ERROR) + @Message(id = 5103, value = "SSL outstanding task loop detected in doWrap/doUnwrap calls. This is indicative of task thread exhaustion so consider investigating any slowness and thread ehxaustion concerns via thread dumps and increasing task-max-threads as needed. Current state %s") + void sslTaskLoopDetected(SslConduit sslConduit); } diff --git a/core/src/main/java/io/undertow/protocols/ssl/SslConduit.java b/core/src/main/java/io/undertow/protocols/ssl/SslConduit.java index 91b6c898d7..9507a4f039 100644 --- a/core/src/main/java/io/undertow/protocols/ssl/SslConduit.java +++ b/core/src/main/java/io/undertow/protocols/ssl/SslConduit.java @@ -170,6 +170,7 @@ public class SslConduit implements StreamSourceConduit, StreamSinkConduit { private SslWriteReadyHandler writeReadyHandler; private SslReadReadyHandler readReadyHandler; private int readListenerInvocationCount; + private int outstandingTaskWaitCount; private boolean invokingReadListenerHandshake = false; @@ -710,7 +711,15 @@ private synchronized long doUnwrap(ByteBuffer[] userBuffers, int off, int len) t throw new ClosedChannelException(); } if(outstandingTasks > 0) { + if(outstandingTaskWaitCount++ == MAX_READ_LISTENER_INVOCATIONS) { + UndertowLogger.REQUEST_LOGGER.sslTaskLoopDetected(this); + IoUtils.safeClose(connection, delegate); + close(); + return -1; + } return 0; + } else { + outstandingTaskWaitCount = 0; } if(anyAreSet(state, FLAG_READ_REQUIRES_WRITE)) { doWrap(null, 0, 0); @@ -919,7 +928,15 @@ private synchronized long doWrap(ByteBuffer[] userBuffers, int off, int len) thr throw new ClosedChannelException(); } if(outstandingTasks > 0) { + if(outstandingTaskWaitCount++ == MAX_READ_LISTENER_INVOCATIONS) { + UndertowLogger.REQUEST_LOGGER.sslTaskLoopDetected(this); + IoUtils.safeClose(connection, delegate); + close(); + return -1; + } return 0; + } else { + outstandingTaskWaitCount = 0; } if(anyAreSet(state, FLAG_WRITE_REQUIRES_READ)) { doUnwrap(null, 0, 0);