diff --git a/src/main/java/io/vertx/core/Future.java b/src/main/java/io/vertx/core/Future.java index 575d14efe00..824026ab536 100644 --- a/src/main/java/io/vertx/core/Future.java +++ b/src/main/java/io/vertx/core/Future.java @@ -683,9 +683,12 @@ static T await(Future future) { } if (future.succeeded()) { return future.result(); - } else { + } else if (future.failed()) { Utils.throwAsUnchecked(future.cause()); return null; + } else { + Utils.throwAsUnchecked(new InterruptedException("Context closed")); + return null; } } diff --git a/src/test/java/io/vertx/core/VirtualThreadContextTest.java b/src/test/java/io/vertx/core/VirtualThreadContextTest.java index b8bed95272c..21739711756 100644 --- a/src/test/java/io/vertx/core/VirtualThreadContextTest.java +++ b/src/test/java/io/vertx/core/VirtualThreadContextTest.java @@ -349,4 +349,31 @@ public void testContextCloseContextSerialization() throws Exception { } f.toCompletionStage().toCompletableFuture().get(20, TimeUnit.SECONDS); } + + @Test + public void testAwaitWhenClosed() throws Exception { + Assume.assumeTrue(isVirtualThreadAvailable()); + ContextInternal ctx = vertx.createVirtualThreadContext(); + CountDownLatch latch = new CountDownLatch(1); + ctx.runOnContext(v -> { + latch.countDown(); + try { + new CountDownLatch(1).await(); + fail(); + } catch (InterruptedException expected) { + assertFalse(Thread.currentThread().isInterrupted()); + } + try { + Promise.promise().future().await(); + fail(); + } catch (Exception e) { + assertEquals(InterruptedException.class, e.getClass()); + testComplete(); + } + }); + awaitLatch(latch); + // Interrupts virtual thread + ctx.close(); + await(); + } }