From 7aa10abee93fa6a3569a9b349ca138a19b9435c1 Mon Sep 17 00:00:00 2001 From: Flavia Rainone Date: Tue, 13 Feb 2024 04:27:55 -0300 Subject: [PATCH] [UNDERTOW-2304] At SslConduit, only delegate handshake task if the task is going to run on a different set of threads than current thread Signed-off-by: Flavia Rainone --- .../io/undertow/protocols/ssl/SslConduit.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) 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 c627256c01..f306ec7fb3 100644 --- a/core/src/main/java/io/undertow/protocols/ssl/SslConduit.java +++ b/core/src/main/java/io/undertow/protocols/ssl/SslConduit.java @@ -206,7 +206,9 @@ public void run() { this.sink = delegate.getSinkChannel().getConduit(); this.source = delegate.getSourceChannel().getConduit(); this.engine = engine; - this.delegatedTaskExecutor = delegatedTaskExecutor; + // if delegatedTaskExecutor is the same as delegate.getWorker, don't set it (see handshake task execution below, + // we need to pick a thread that is different from the current thread running or run the handshake task immediately at the same thread) + this.delegatedTaskExecutor = this.delegate.getWorker() != delegatedTaskExecutor? delegatedTaskExecutor : null; this.bufferPool = bufferPool; delegate.getSourceChannel().getConduit().setReadReadyHandler(readReadyHandler = new SslReadReadyHandler(null)); delegate.getSinkChannel().getConduit().setWriteReadyHandler(writeReadyHandler = new SslWriteReadyHandler(null)); @@ -1173,7 +1175,16 @@ public void run() { } }; try { - getDelegatedTaskExecutor().execute(wrappedTask); + // we want to pick a thread different from the one we are running, to prevent starvation scenarios + // for example where we repeatedly attempt to write or read but are stuck waiting on a handshake task + // and the handshake task rarely has the chance to run because it needs the read/write thread to complete execution + // so, if io thread (read and write thread) is the same as current thread, and getDelegatedTaskExecutor will delegate + // execution to the same set of threads we are currently at, just run the handshake task right away to prevent blocking + if (delegate.getIoThread().equals(Thread.currentThread()) && delegatedTaskExecutor == null) { + wrappedTask.run(); + } else { + getDelegatedTaskExecutor().execute(wrappedTask); + } } catch (RejectedExecutionException e) { UndertowLogger.REQUEST_IO_LOGGER.sslEngineDelegatedTaskRejected(e); IoUtils.safeClose(connection);