ITADN

kqueue backend: in-process waker does not interrupt kevent() poll

#928Closedpaddor 创建于 2026-05-21
bughelp wanteddriver: polling
P
paddorcommented
On macOS (kqueue backend), a task woken by an in-process event (e.g. flume channel send) is not scheduled promptly when the runtime is blocked in `kevent()`. The waker notification does not interrupt the kernel poll, so the woken task only runs after an unrelated I/O event or timer fires. On the io_uring backend (Linux), the same scenario works correctly. Repro: ```rust use std::time::Duration; #[compio::main] async fn main() { let (tx, rx) = flume::bounded::<u32>(1); // Spawned task: wait for a message, then print it. compio::runtime::spawn(async move { let val = rx.recv_async().await.unwrap(); println!("received: {val}"); }) .detach(); // Let the spawned task park on recv_async. compio::time::sleep(Duration::from_millis(50)).await; // Send a message. flume wakes the spawned task's waker. tx.send(42).unwrap(); // This sleep should let the spawned task run, but on macOS // the runtime enters kevent() without checking for ready tasks, // so the spawned task never runs until this timer fires. compio::time::sleep(Duration::from_millis(500)).await; // On Linux: "received: 42" prints almost instantly. // On macOS: "received: 42" prints after the full 500ms, // or not at all if replaced with a future that // blocks on the spawned task's output. } ``` Replace the final `sleep` with a future that depends on the spawned task completing (e.g. waiting for data the spawned task would write to a socket), and the program deadlocks on macOS. ## Expected behavior When a task's `Waker` is invoked (by flume, tokio::sync, event-listener, or any other in-process notification), the runtime should break out of `kevent()` and schedule the woken task before re-entering the kernel poll. io_uring backends typically use an eventfd registered with the submission queue for this purpose. The kqueue equivalent would be `EVFILT_USER` or a self-pipe. ## Observed behavior On macOS, the woken task is not scheduled until the next unrelated I/O completion or timer expiry causes `kevent()` to return. If no other event is pending, the woken task starves. ## Environment - compio 0.19.0-rc.2 / compio-driver 0.12.0-rc.2 - macOS 15.7.3 - `rustc 1.95.0 (59807616e 2026-04-14) (Homebrew)`
关闭于 2026-05-24 19 条评论