OnceLock::wait was stabilized in Rust 1.86, so its use in the Windows
console ctrl handler broke tokio's declared rust-version of 1.71 on
windows targets in 1.53.0 (any cargo check with a 1.71..1.86 toolchain
fails with E0599).
The wait existed only because SetConsoleCtrlHandler was called inside
REGISTRY's get_or_init closure, i.e. before the OnceLock was actually
initialized, leaving a window where an invoked handler could observe an
uninitialized REGISTRY. Initialize the registry first and register the
OS handler afterwards (exactly once, through a second OnceLock that
also caches a registration failure so every subsequent call reports the
same error, matching the previous behavior). The handler can then rely
on plain get(): registration happens-after initialization, so an
invoked handler always finds the registry.
Verified with cargo +1.71 check -p tokio --features full
--target x86_64-pc-windows-msvc (fails with the reported E0599 before
this change, clean after) and --all-targets on stable for the same
target.
Fixes#8299
QNX (nto) does not provide LOCAL_PEEREID, which is used by the
impl_netbsd module. This causes a compilation failure on QNX.
Use getpeereid() instead, following the same pattern as impl_dragonfly
and impl_aix. This provides uid/gid but not pid, so UCred::pid()
returns None on QNX.
Option::filter() exists since Rust 1.27.0, and is much more readable
than the open coded variant that was there before, using
Option::and_then().
This has been found by clippy.
This impl was missing to be able to create a tokio::fs::File directly
from an OwnedFd, which can be done in a safe way. Going through RawFd
required unsafe for the same operation.
And same for Windows using a OwnedHandle instead.
Since #5223, `yield_now` does not wake the task immediately. Instead,
the waker is handed to the scheduler via `context::defer`, which wakes
it only after running out of ready tasks and polling the IO/timer
driver. Add a comment explaining this, as the reasoning is not obvious
from the bare `context::defer` call.
I recently fixed a memory leak in an application where tokio's RawTask
storage was being kept alive by a leaked Waker. The task itself was
polling an `mpsc::Receiver` before then being aborted. During cleanup,
all references to the RawTask were dropped, except for the one stored in
`mpsc::chan::Chan::rx_waker`. While the `Receiver` was dropped as part
of the task's future, one of the channel's `Sender`s was leaked outside
the task. This meant the `Chan` was never dropped and its `rx_waker`
contained the leaked Waker.
I fixed the leak by properly cleaning up the `Sender`, but I also think
keeping `rx_waker` around in this case is unnecessary. Once `chan::Rx`
is dropped, it can't be polled anymore, so waking up the registered task
will always be spurious.
The commit includes a regression test to illustrate the problem that is
fixed by removing the waker explicitly.
Expand module and API docs around RecvError::Lagged / TryRecvError::Lagged
so capacity rounding, miss counts, and post-lag resume behavior are explicit.
Add integration tests covering slow receivers within capacity, overflow,
per-receiver lag, async recv, and cursor advancement after Lagged.
Add #[inline] hints to poll_read, poll_write, start_seek, poll_complete, poll_fill_buf, and consume implementations for in-memory types (&[u8], Vec<u8>, Cursor<T>).
These are small, leaf implementations that benefit from cross-crate inlining, enabling LLVM to optimize call sites in downstream crates (including bounds-check elision and dead-code path elimination).
Benchmarks show ~16% improvement for slice reads and ~20% for cursor writes.