vanilla_io_uring fails CI: io_uring is blocked by Docker's default seccomp on GitHub Actions

Author: enghitaloCreated Jun 16, 2026Updated Jun 16, 2026

Summary

The V vanilla_io_uring framework cannot pass the GitHub Actions CI smoke-test because io_uring is blocked by Docker's default seccomp profile on the runners. It builds and starts, but io_uring_setup/io_uring_enter are denied, so it never opens a ring and never becomes HTTP-ready.

Failing run: https://github.com/the-benchmarker/web-frameworks/actions/runs/27570918190/job/81506991936 (PR #9466)

Container did not become ready in 120 seconds!
Failed to initialize io_uring for worker 0:
  io_uring_queue_init_params failed for all ring entry/flag combinations

In the same run, vanilla_epoll, pico, fasthttp and veb all pass with the same V toolchain — only the io_uring variant fails, at the docker run readiness step (not at build). Since ~Docker 20.10 the default seccomp profile blocks the io_uring_* syscalls (io_uring submissions can bypass per-syscall seccomp filtering, so it's denied by default).

Action taken

Removed the vanilla_io_uring framework from this repo (PR #9466). Rather than carry a framework that can't pass the smoke-test (or paper over it with a per-framework CI skip), it's dropped here. vanilla_epoll stays, and the io_uring engine continues to be benchmarked in HttpArena, whose harness permits io_uring.

If io_uring support is wanted here later — the fair way

Running just the io_uring container with --security-opt seccomp=unconfined would make it pass, but it's unfair: that container would run less sandboxed than its peers (seccomp adds a small per-syscall cost), so its numbers wouldn't be comparable, and unconfined drops the whole sandbox rather than just io_uring.

The fair approach is a single custom seccomp profile applied uniformly to every framework: take Docker's default profile, add io_uring_setup, io_uring_enter, io_uring_register to the allow-list, and pass --security-opt seccomp=<profile>.json on every docker run.

  • Frameworks that don't use io_uring are bit-for-bit unaffected (the added entries are never hit) — no perf change, no re-baseline.
  • io_uring frameworks can initialize their rings.
  • Everyone runs under the identical filter, so comparability is preserved and only the legitimate I/O-model difference remains.

Trade-off: this re-opens the io_uring/seccomp escape vector for all containers (acceptable for a trusted, ephemeral benchmark harness), and it must also apply on the real benchmark host. Happy to send a PR with the profile + the global flag if that direction is wanted.

Source: the-benchmarker/web-frameworks