diff --git a/tests/io/CancelFutureTest.cpp b/tests/io/CancelFutureTest.cpp
index bdd3bc9058f9093611fafe1071d22cef2062fb47..822ae13c51c145a29f1689efa9afa75a6ad465b2 100644
--- a/tests/io/CancelFutureTest.cpp
+++ b/tests/io/CancelFutureTest.cpp
@@ -4,11 +4,18 @@
 
 #include <cerrno>		// for ECANCELED, ETIME
 #include <cstdint>	// for uint64_t, int32_t
+#include <memory>
 
 #include "Common.hpp"
+#include "CountingPrivateSemaphore.hpp"
 #include "Emper.hpp"
+#include "Runtime.hpp"
+#include "Semaphore.hpp"
+#include "emper.hpp"
 #include "fixtures/assert.hpp"
-#include "io/Future.hpp"	// for ReadFuture, WriteFuture
+#include "io.hpp"
+#include "io/Future.hpp"
+#include "lib/LinuxVersion.hpp"
 
 using emper::io::ReadFuture;
 using emper::io::WriteFuture;
@@ -75,6 +82,69 @@ static void cancelPartialCompletedChain() {
 	ASSERT(readFuture.wait() == sizeof(write_buf) && read_buf == write_buf);
 }
 
+/**
+ * @brief Cancel a lot of read futures hopefully going through scheduleOn
+ *
+ * The test uses one fiber per worker. Each fiber creates an eventfd, prepares
+ * and submits a ReadFuture. Then each Fiber yields and creates a second ReadFuture.
+ * After all Fibers are done with this preparation each will issue a write to the
+ * next eventfd.
+ * Each fiber yields a last time to change the worker and exit resulting in
+ * cancellation of two Futures one possible completed and one definitely outstanding.
+ */
+static void massCancelOnDifferentWorker() {
+	const unsigned fiberCount = Runtime::getRuntime()->getWorkerCount() * 5;
+	int* evfds = new int[fiberCount];
+	emper::Semaphore readySem;
+	emper::Semaphore startSem;
+
+	CPS cps;
+	for (unsigned i = 0; i < fiberCount; ++i) {
+		spawn(
+				[&, i = i] {
+					uint64_t rbuf = 0;
+					const uint64_t wbuf = i;
+
+					evfds[i] = eventfd(0, 0);
+
+					ReadFuture rf(evfds[i], &rbuf, sizeof(rbuf), 0);
+					rf.submit();
+
+					emper::yield();
+
+					ReadFuture rf2(evfds[i], &rbuf, sizeof(rbuf), 0);
+					rf2.submit();
+
+					readySem.release();
+					startSem.acquire();
+
+					WriteFuture wf(evfds[(i + 1) % fiberCount], &wbuf, sizeof(wbuf), 0);
+					wf.submitAndWait();
+
+					emper::yield();
+					rf.cancel();
+					rf2.cancel();
+				},
+				cps);
+	}
+
+	for (unsigned i = 0; i < fiberCount; ++i) {
+		readySem.acquire();
+	}
+
+	for (unsigned i = 0; i < fiberCount; ++i) {
+		startSem.release();
+	}
+	cps.wait();
+
+	CPS closeCps;
+	for (unsigned i = 0; i < fiberCount; ++i) {
+		spawn([&, i = i] { emper::io::closeAndForget(evfds[i]); }, closeCps);
+	}
+	closeCps.wait();
+	delete[] evfds;
+}
+
 void emperTest() {
 	efd = eventfd(0, 0);
 	if (efd == -1) {
@@ -87,4 +157,12 @@ void emperTest() {
 	cancelCompleted();
 	cancelNotCompletedChain();
 	cancelPartialCompletedChain();
+
+	// Async cancelation is racy before linux 5.17.
+	// Work may be not found at all or only the work is cancelled but
+	// not the armed poll.
+	// https://lore.kernel.org/io-uring/20220119024241.609233-1-axboe@kernel.dk/T/#t
+	if (EMPER_LINUX_GE("5.17.0")) {
+		massCancelOnDifferentWorker();
+	}
 }