|
3 | 3 | import static java.util.concurrent.StructuredTaskScope.Joiner.allSuccessfulOrThrow; |
4 | 4 | import static org.junit.jupiter.api.Assertions.*; |
5 | 5 |
|
| 6 | +import java.lang.ref.SoftReference; |
| 7 | +import java.lang.ref.WeakReference; |
6 | 8 | import java.net.InetSocketAddress; |
7 | 9 | import java.net.URI; |
8 | 10 | import java.net.http.HttpClient; |
|
39 | 41 | import io.netty.util.ReferenceCountUtil; |
40 | 42 | import io.netty.util.concurrent.EventExecutor; |
41 | 43 | import io.netty.util.internal.ThreadExecutorMap; |
| 44 | +import org.junit.jupiter.api.Timeout; |
42 | 45 |
|
43 | 46 | public class VirtualMultithreadIoEventLoopGroupTest { |
44 | 47 |
|
@@ -366,6 +369,32 @@ void schedulerIsNotInheritedByForkedVT() throws InterruptedException, ExecutionE |
366 | 369 | } |
367 | 370 | } |
368 | 371 |
|
| 372 | + @Test |
| 373 | + @Timeout(10) |
| 374 | + void schedulerIsNotLeakingIfItsThreadFactoryOutliveIt() throws InterruptedException, ExecutionException { |
| 375 | + ThreadFactory vThreadFactory; |
| 376 | + WeakReference<EventLoopScheduler> schedulerWeakRef; |
| 377 | + EventLoopScheduler.SharedRef schedulerRef; |
| 378 | + try (var group = new VirtualMultithreadIoEventLoopGroup(1, LocalIoHandler.newFactory())) { |
| 379 | + vThreadFactory = group.submit(group::vThreadFactory).get(); |
| 380 | + schedulerRef = group.submit(() -> EventLoopScheduler.currentThreadSchedulerContext().scheduler()).get(); |
| 381 | + schedulerWeakRef = new WeakReference<>(schedulerRef.get()); |
| 382 | + } |
| 383 | + while (schedulerRef.get() != null) { |
| 384 | + Thread.yield(); |
| 385 | + } |
| 386 | + while (schedulerWeakRef.get() != null) { |
| 387 | + System.gc(); |
| 388 | + System.runFinalization(); |
| 389 | + Thread.sleep(100); |
| 390 | + } |
| 391 | + // we can still run virtual threads from the factory without the scheduler |
| 392 | + var schedulerRefPromise = new CompletableFuture<EventLoopScheduler.SharedRef>(); |
| 393 | + vThreadFactory.newThread(() -> schedulerRefPromise.complete(EventLoopScheduler.currentThreadSchedulerContext().scheduler())).start(); |
| 394 | + assertSame(schedulerRef, schedulerRefPromise.get()); |
| 395 | + assertNull(schedulerRefPromise.get().get()); |
| 396 | + } |
| 397 | + |
369 | 398 | @Test |
370 | 399 | void virtualThreadCanMakeProgressEvenIfEventLoopIsClosed() throws InterruptedException, ExecutionException, BrokenBarrierException, TimeoutException { |
371 | 400 | var group = new VirtualMultithreadIoEventLoopGroup(1, LocalIoHandler.newFactory()); |
|
0 commit comments