From 0e412f1cd8671480dcc6ccb58b95a5ab9d52df00 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Wed, 21 Jul 2021 16:50:31 +0100 Subject: [PATCH] Reset the current context Classloader on the threads of the Vertx blocking executor pool --- .../vertx/core/runtime/VertxCoreRecorder.java | 46 ++++++++++++++----- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/extensions/vertx-core/runtime/src/main/java/io/quarkus/vertx/core/runtime/VertxCoreRecorder.java b/extensions/vertx-core/runtime/src/main/java/io/quarkus/vertx/core/runtime/VertxCoreRecorder.java index ed799c7014cdd..c7c0357c730ee 100644 --- a/extensions/vertx-core/runtime/src/main/java/io/quarkus/vertx/core/runtime/VertxCoreRecorder.java +++ b/extensions/vertx-core/runtime/src/main/java/io/quarkus/vertx/core/runtime/VertxCoreRecorder.java @@ -7,6 +7,8 @@ import static io.quarkus.vertx.core.runtime.SSLConfigHelper.configurePfxTrustOptions; import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -25,6 +27,7 @@ import org.jboss.logging.Logger; import org.jboss.threads.ContextHandler; +import org.jboss.threads.EnhancedQueueExecutor; import org.wildfly.common.cpu.ProcessorInfo; import io.netty.channel.EventLoopGroup; @@ -41,7 +44,6 @@ import io.vertx.core.AsyncResult; import io.vertx.core.Context; import io.vertx.core.Handler; -import io.vertx.core.Promise; import io.vertx.core.Vertx; import io.vertx.core.VertxOptions; import io.vertx.core.dns.AddressResolverOptions; @@ -53,6 +55,7 @@ import io.vertx.core.impl.VertxBuilder; import io.vertx.core.impl.VertxImpl; import io.vertx.core.impl.VertxThread; +import io.vertx.core.impl.WorkerPool; import io.vertx.core.spi.VertxThreadFactory; import io.vertx.core.spi.resolver.ResolverProvider; @@ -129,19 +132,14 @@ public void handle(AsyncResult event) { private void tryCleanTccl(Vertx devModeVertx) { //this is a best effort attempt to clean out the old TCCL from ClassLoader cl = Thread.currentThread().getContextClassLoader(); - for (int i = 0; i < blockingThreadPoolSize; ++i) { - devModeVertx.executeBlocking(new Handler>() { - @Override - public void handle(Promise event) { - Thread.currentThread().setContextClassLoader(cl); - try { - Thread.sleep(50); - } catch (InterruptedException e) { - } - } - }, null); + EnhancedQueueExecutor executor = extractExecutor(devModeVertx); + + final Thread[] runningThreads = executor.getRunningThreads(); + for (Thread t : runningThreads) { + t.setContextClassLoader(cl); } + EventLoopGroup group = ((VertxImpl) devModeVertx).getEventLoopGroup(); for (EventExecutor i : group) { i.execute(new Runnable() { @@ -156,6 +154,30 @@ public void run() { } + /** + * Extract the JBoss Threads EnhancedQueueExecutor from the Vertx instance + * this is messy as it needs to use reflection until Vertx can expose it. + */ + private EnhancedQueueExecutor extractExecutor(Vertx devModeVertx) { + final ContextInternal ctx = (ContextInternal) devModeVertx.getOrCreateContext(); + final WorkerPool workerPool = ctx.workerPool(); + final Method executorMethod; + try { + executorMethod = WorkerPool.class.getDeclaredMethod("executor"); + executorMethod.setAccessible(true); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + final Object result; + try { + result = executorMethod.invoke(workerPool); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + EnhancedQueueExecutor executor = (EnhancedQueueExecutor) result; + return executor; + } + public IOThreadDetector detector() { return new IOThreadDetector() { @Override