diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 54a2c3d87..99d1fdfd1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -9,6 +9,8 @@ jobs: ci: name: CI runs-on: ${{ matrix.os }} + # a hung test fails in an hour instead of at GitHub's 6 hour default + timeout-minutes: 60 continue-on-error: true strategy: fail-fast: false diff --git a/runtime/src/test/java/run/endive/runtime/MemoryTest.java b/runtime/src/test/java/run/endive/runtime/MemoryTest.java index a9ddd6e83..6fb6cecdc 100644 --- a/runtime/src/test/java/run/endive/runtime/MemoryTest.java +++ b/runtime/src/test/java/run/endive/runtime/MemoryTest.java @@ -6,6 +6,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; @@ -285,18 +286,22 @@ public void waitAndNotifyWithAtomicsOnSameWord(String name, Supplier mem memory.atomicWriteInt(addr, 0); var stop = new AtomicBoolean(); + // not the common pool: on a 3-core runner it can leave the waiter queued behind adds + var threads = Executors.newFixedThreadPool(2); var adds = CompletableFuture.runAsync( () -> { while (!stop.get()) { memory.atomicAddInt(0, 1); } - }); + }, + threads); try { for (int round = 0; round < 100; round++) { var waiter = CompletableFuture.supplyAsync( - () -> memory.atomicWait(addr, 0, TimeUnit.SECONDS.toNanos(30))); + () -> memory.atomicWait(addr, 0, TimeUnit.SECONDS.toNanos(30)), + threads); while (memory.atomicNotify(addr, 1) == 0 && !waiter.isDone()) { Thread.onSpinWait(); } @@ -304,6 +309,7 @@ public void waitAndNotifyWithAtomicsOnSameWord(String name, Supplier mem } } finally { stop.set(true); + threads.shutdown(); } adds.get(30, TimeUnit.SECONDS); }