kqueue backend: in-process waker does not interrupt kevent() poll
bughelp wanteddriver: polling
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 条评论