From 181597b943c623ff4471eafb5ae6ce1a05a8d952 Mon Sep 17 00:00:00 2001 From: Clement Escoffier Date: Mon, 8 Mar 2021 15:24:30 +0100 Subject: [PATCH 1/3] Create /tmp/vertx-cache and configure it to be world-readable and writable. Under that directory, another random directory is created that is only readable and writable from the current user. The vertx-cache directory creation is disabled if: * the user specifies a cache directory * the vertx-cache directory already exists Fix #7678 --- .../vertx/core/runtime/VertxCoreRecorder.java | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 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 d682a9612b87f..173119913dbad 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 @@ -13,6 +13,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -51,6 +52,7 @@ public class VertxCoreRecorder { private static final Logger LOGGER = Logger.getLogger(VertxCoreRecorder.class.getName()); + public static final String VERTX_CACHE = "vertx-cache"; static volatile VertxSupplier vertx; @@ -227,8 +229,24 @@ private static VertxOptions convertToVertxOptions(VertxConfiguration conf, Vertx initializeClusterOptions(conf, options); } - String fileCacheDir = System.getProperty(CACHE_DIR_BASE_PROP_NAME, - System.getProperty("java.io.tmpdir", ".") + File.separator + "vertx-cache"); + String fileCacheDir = System.getProperty(CACHE_DIR_BASE_PROP_NAME); + if (fileCacheDir == null) { + File tmp = new File(System.getProperty("java.io.tmpdir", ".") + File.separator + VERTX_CACHE); + if (!tmp.isDirectory()) { + if (!tmp.mkdirs()) { + LOGGER.warnf("Unable to create Vert.x cache directory : %s", tmp.getAbsolutePath()); + } + if (!(tmp.setReadable(true, false) && tmp.setWritable(true, false))) { + LOGGER.warnf("Unable to make the Vert.x cache directory (%s) world readable and writable", + tmp.getAbsolutePath()); + } + } + + long random = UUID.randomUUID().getMostSignificantBits(); + File cache = new File(tmp, Long.toString(random)); + LOGGER.debugf("Vert.x Cache configured to: %s", cache.getAbsolutePath()); + fileCacheDir = cache.getAbsolutePath(); + } options.setFileSystemOptions(new FileSystemOptions() .setFileCachingEnabled(conf.caching) From 394286eca79c9724b4026760f4b4c723555a6ff0 Mon Sep 17 00:00:00 2001 From: Clement Escoffier Date: Tue, 9 Mar 2021 11:12:26 +0100 Subject: [PATCH 2/3] Cleanup the created (random) cache directory during shutdown --- .../vertx/core/runtime/VertxCoreRecorder.java | 65 ++++++++++++++----- .../core/runtime/VertxCoreProducerTest.java | 6 +- .../vertx/runtime/VertxProducerTest.java | 2 +- 3 files changed, 52 insertions(+), 21 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 173119913dbad..8bfdb72dff537 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 @@ -67,7 +67,7 @@ public class VertxCoreRecorder { public Supplier configureVertx(VertxConfiguration config, LaunchMode launchMode, ShutdownContext shutdown, List> customizers) { if (launchMode != LaunchMode.DEVELOPMENT) { - vertx = new VertxSupplier(config, customizers); + vertx = new VertxSupplier(config, customizers, shutdown); // we need this to be part of the last shutdown tasks because closing it early (basically before Arc) // could cause problem to beans that rely on Vert.x and contain shutdown tasks shutdown.addLastShutdownTask(new Runnable() { @@ -78,7 +78,7 @@ public void run() { }); } else { if (vertx == null) { - vertx = new VertxSupplier(config, customizers); + vertx = new VertxSupplier(config, customizers, shutdown); } else if (vertx.v != null) { tryCleanTccl(vertx.v); } @@ -174,12 +174,12 @@ public static Supplier getVertx() { return vertx; } - public static Vertx initialize(VertxConfiguration conf, VertxOptionsCustomizer customizer) { + public static Vertx initialize(VertxConfiguration conf, VertxOptionsCustomizer customizer, ShutdownContext shutdown) { VertxOptions options = new VertxOptions(); if (conf != null) { - convertToVertxOptions(conf, options, true); + convertToVertxOptions(conf, options, true, shutdown); } // Allow extension customizers to do their thing @@ -190,11 +190,14 @@ public static Vertx initialize(VertxConfiguration conf, VertxOptionsCustomizer c Vertx vertx; if (options.getEventBusOptions().isClustered()) { CompletableFuture latch = new CompletableFuture<>(); - Vertx.clusteredVertx(options, ar -> { - if (ar.failed()) { - latch.completeExceptionally(ar.cause()); - } else { - latch.complete(ar.result()); + Vertx.clusteredVertx(options, new Handler>() { + @Override + public void handle(AsyncResult ar) { + if (ar.failed()) { + latch.completeExceptionally(ar.cause()); + } else { + latch.complete(ar.result()); + } } }); vertx = latch.join(); @@ -215,7 +218,8 @@ private static Vertx logVertxInitialization(Vertx vertx) { return vertx; } - private static VertxOptions convertToVertxOptions(VertxConfiguration conf, VertxOptions options, boolean allowClustering) { + private static VertxOptions convertToVertxOptions(VertxConfiguration conf, VertxOptions options, boolean allowClustering, + ShutdownContext shutdown) { if (!conf.useAsyncDNS) { System.setProperty(ResolverProvider.DISABLE_DNS_RESOLVER_PROP_NAME, "true"); @@ -246,6 +250,17 @@ private static VertxOptions convertToVertxOptions(VertxConfiguration conf, Vertx File cache = new File(tmp, Long.toString(random)); LOGGER.debugf("Vert.x Cache configured to: %s", cache.getAbsolutePath()); fileCacheDir = cache.getAbsolutePath(); + if (shutdown != null) { + shutdown.addLastShutdownTask(new Runnable() { + @Override + public void run() { + // Recursively delete the created directory and all the files + deleteDirectory(cache); + // We do not delete the vertx-cache directory on purpose, as it could be used concurrently by + // another application. In the worse case, it's just an empty directory. + } + }); + } } options.setFileSystemOptions(new FileSystemOptions() @@ -295,11 +310,14 @@ void destroy() { FastThreadLocal.destroy(); CountDownLatch latch = new CountDownLatch(1); AtomicReference problem = new AtomicReference<>(); - vertx.v.close(ar -> { - if (ar.failed()) { - problem.set(ar.cause()); + vertx.v.close(new Handler>() { + @Override + public void handle(AsyncResult ar) { + if (ar.failed()) { + problem.set(ar.cause()); + } + latch.countDown(); } - latch.countDown(); }); try { latch.await(); @@ -411,24 +429,27 @@ public Integer get() { } public static Supplier recoverFailedStart(VertxConfiguration config) { - return vertx = new VertxSupplier(config, Collections.emptyList()); + return vertx = new VertxSupplier(config, Collections.emptyList(), null); } static class VertxSupplier implements Supplier { final VertxConfiguration config; final VertxOptionsCustomizer customizer; + final ShutdownContext shutdown; Vertx v; - VertxSupplier(VertxConfiguration config, List> customizers) { + VertxSupplier(VertxConfiguration config, List> customizers, + ShutdownContext shutdown) { this.config = config; this.customizer = new VertxOptionsCustomizer(customizers); + this.shutdown = shutdown; } @Override public synchronized Vertx get() { if (v == null) { - v = initialize(config, customizer); + v = initialize(config, customizer, shutdown); } return v; } @@ -452,4 +473,14 @@ VertxOptions customize(VertxOptions options) { public static void setWebDeploymentId(String webDeploymentId) { VertxCoreRecorder.webDeploymentId = webDeploymentId; } + + private static void deleteDirectory(File directory) { + File[] children = directory.listFiles(); + if (children != null) { + for (File child : children) { + deleteDirectory(child); + } + } + directory.delete(); + } } diff --git a/extensions/vertx-core/runtime/src/test/java/io/quarkus/vertx/core/runtime/VertxCoreProducerTest.java b/extensions/vertx-core/runtime/src/test/java/io/quarkus/vertx/core/runtime/VertxCoreProducerTest.java index ba26cdbbabd30..3a0605f67c4fe 100644 --- a/extensions/vertx-core/runtime/src/test/java/io/quarkus/vertx/core/runtime/VertxCoreProducerTest.java +++ b/extensions/vertx-core/runtime/src/test/java/io/quarkus/vertx/core/runtime/VertxCoreProducerTest.java @@ -55,7 +55,7 @@ public void shouldEnableClustering() { configuration.cluster = cc; try { - VertxCoreRecorder.initialize(configuration, null); + VertxCoreRecorder.initialize(configuration, null, null); Assertions.fail("It should not have a cluster manager on the classpath, and so fail the creation"); } catch (IllegalStateException e) { Assertions.assertTrue(e.getMessage().contains("No ClusterManagerFactory"), @@ -82,7 +82,7 @@ public void accept(VertxOptions vertxOptions) { } })); - VertxCoreRecorder.initialize(configuration, customizers); + VertxCoreRecorder.initialize(configuration, customizers, null); } @Test @@ -95,7 +95,7 @@ public void accept(VertxOptions vertxOptions) { called.set(true); } })); - Vertx v = VertxCoreRecorder.initialize(createDefaultConfiguration(), customizers); + Vertx v = VertxCoreRecorder.initialize(createDefaultConfiguration(), customizers, null); Assertions.assertTrue(called.get(), "Customizer should get called during initialization"); } diff --git a/extensions/vertx/runtime/src/test/java/io/quarkus/vertx/runtime/VertxProducerTest.java b/extensions/vertx/runtime/src/test/java/io/quarkus/vertx/runtime/VertxProducerTest.java index 5d0bc6b9de611..557f0d4096965 100644 --- a/extensions/vertx/runtime/src/test/java/io/quarkus/vertx/runtime/VertxProducerTest.java +++ b/extensions/vertx/runtime/src/test/java/io/quarkus/vertx/runtime/VertxProducerTest.java @@ -28,7 +28,7 @@ public void tearDown() { @Test public void shouldNotFailWithoutConfig() { - verifyProducer(VertxCoreRecorder.initialize(null, null)); + verifyProducer(VertxCoreRecorder.initialize(null, null, null)); } private void verifyProducer(Vertx v) { From f4a6aaf751b27262d8a4422304f4db6969306771 Mon Sep 17 00:00:00 2001 From: Clement Escoffier Date: Tue, 9 Mar 2021 11:36:18 +0100 Subject: [PATCH 3/3] Improve random directory generation: * make sure it does not exist * avoid negative numbers --- .../vertx/core/runtime/VertxCoreRecorder.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 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 8bfdb72dff537..adf16ee6d25f7 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 @@ -246,8 +246,7 @@ private static VertxOptions convertToVertxOptions(VertxConfiguration conf, Vertx } } - long random = UUID.randomUUID().getMostSignificantBits(); - File cache = new File(tmp, Long.toString(random)); + File cache = getRandomDirectory(tmp); LOGGER.debugf("Vert.x Cache configured to: %s", cache.getAbsolutePath()); fileCacheDir = cache.getAbsolutePath(); if (shutdown != null) { @@ -291,6 +290,16 @@ public void run() { return options; } + private static File getRandomDirectory(File tmp) { + long random = Math.abs(UUID.randomUUID().getMostSignificantBits()); + File cache = new File(tmp, Long.toString(random)); + if (cache.isDirectory()) { + // Do not reuse an existing directory. + return getRandomDirectory(tmp); + } + return cache; + } + private static int calculateDefaultIOThreads() { //we only allow one event loop per 10mb of ram at the most //its hard to say what this number should be, but it is also obvious