Tokio Knowledge Patch
Use this skill for version-sensitive Tokio work: dependency selection, runtime
construction, task behavior, channels, asynchronous I/O, networking, processes,
signals, and the companion tokio-util and tokio-stream crates. Check the
project manifest first and apply only guidance relevant to its pinned versions.
Reference index
| Reference |
Topics |
| compatibility.md |
Toolchain floors, safe patch releases, target support, and unstable configuration |
| runtime-and-tasks.md |
Runtime construction, scheduling, task APIs, metrics, hooks, and diagnostics |
| synchronization.md |
watch, broadcast, mpsc, oneshot, Notify, semaphores, and RwLock |
| io-and-filesystem.md |
Async I/O types, files, pipes, AIO, io_uring, and standard output |
| networking-process-signals.md |
Sockets, target-specific networking, child processes, and signals |
| tokio-util-and-stream.md |
Compatibility and APIs in tokio-util and tokio-stream |
Upgrade gates
Select safe patch releases
- Use at least 1.42.1 when a
broadcast channel may carry Send but !Sync
values; 1.42.0 has an unsynchronized-clone soundness bug.
- On the 1.43 line, use 1.43.4 to include the pidfd, receiverless-broadcast,
and closed-and-drained
mpsc::try_recv corrections.
- Use at least 1.45.1 on
wasm32-unknown-unknown; time-based metrics in 1.45.0
can make valid Instant::now() calls panic.
- Use at least 1.46.1 when task hooks inspect
TaskMeta::spawned_at for tasks
created with tokio::spawn.
- On the 1.47 line, use 1.47.5 for channel length, permit wakeup, outstanding
permit, and
RwLock limit behavior; 1.47.4 also fixes recv_many on a closed
channel, and 1.47.2 fixes join!/try_join! hygiene.
- Use at least 1.51.1 when semaphore closure, Linux UDP pending errors, or
cancellable io_uring opens matter.
- Do not remain on 1.52.0 when using
spawn_blocking; require 1.52.1 to avoid a
sharded blocking-queue hang.
- Use 1.53.1 for Windows signal support at the Rust 1.71 minimum and for the
unstable alternate-timer cancellation race fix.
See compatibility.md for exact patch-line floors
and older-line backports.
Enforce compiler and dependency floors
| Package |
Minimum toolchain or dependency |
| Tokio from 1.39.0 |
Rust 1.70 |
| Tokio from 1.48.0 |
Rust 1.71 |
tokio-util 0.7.12 |
Rust 1.70 |
tokio-util 0.7.17 |
Rust 1.71 |
tokio-util 0.7.18 |
Tokio 1.44.0 |
tokio-stream 0.1.16 |
Rust 1.70 |
Adjust rejected or changed code
- Put every standard-library socket into nonblocking mode before a Tokio
from_std conversion; blocking sockets panic from 1.44.0 onward.
let listener = std::net::TcpListener::bind(addr)?;
listener.set_nonblocking(true)?;
let listener = tokio::net::TcpListener::from_std(listener)?;
- Keep
runtime::Builder::event_interval nonzero; event_interval(0) panics
from 1.50.0 onward.
- Keep blocking work out of futures and destructors polled or dropped by a
LocalSet from 1.46.0 onward. Use spawn_blocking or move it outside.
- Replace deprecated
TcpStream::set_linger and TcpSocket::set_linger calls.
Use TcpStream::set_zero_linger() for abortive close from 1.50.0.
- Await, retain, or explicitly discard
JoinHandle::abort_handle() and
Notify::notified() results; their types are #[must_use].
- Do not interpret a signal receive result of
None as shutdown; signal
listeners remain open from 1.50.0 onward.
- Expect task-owned state to be dropped before its
JoinHandle completes from
1.50.0 onward.
- Reuse or synchronize one Tokio standard-output handle when write ordering
matters; independent handles may reorder writes.
Update unstable builds
- Select
taskdump and io_uring with Cargo features from 1.48.0; replace the
former custom --cfg switches.
- Pass
LocalOptions by value to unstable Builder::build_local from 1.46.0.
- Migrate off the removed unstable alternate multi-threaded runtime before
using 1.45.0 or newer.
- Treat io_uring as opportunistic: Tokio may disable it after
EPERM, and the
operations available through the backend depend on the Tokio release.
Runtime and task quick reference
Choose local execution deliberately
- Use stable
tokio::runtime::LocalRuntime from 1.51.0 for thread-local
!Send tasks. Earlier forms were unstable.
- The unstable macro flavor
#[tokio::main(flavor = "local")] is available
from 1.48.0.
- Use stable
runtime::id::Id and LocalSet::id() from 1.49.0 for diagnostic
identity.
- From 1.51.0, assign runtime names and use
runtime::worker_index() for
per-worker diagnostic context.
Preserve cooperative scheduling
watch receives and broadcast::Receiver participate in cooperative
scheduling from 1.41.0.
select! consumes cooperative budget from 1.44.0.
- Use
task::coop for custom asynchronous resources from 1.44.0;
cooperative and poll_proceed arrive in 1.47.0.
yield_now takes effect immediately inside block_in_place from 1.42.0.
Use current task primitives
- Use
tokio::sync::SetOnce from 1.47.0 for asynchronously observable,
single-assignment state.
- Use
Notify::notified_owned() and OwnedNotified from 1.47.0 when the
notification future must not borrow its Notify.
- Extend
JoinSet<T> from an iterator from 1.49.0.
- Sort
task::Id values or use them as ordered keys from 1.48.0.
- Use
LocalKey::try_get() from 1.48.0 when missing task-local state should not
panic.
Interpret metrics carefully
- Stable global queue depth arrives in 1.41.0; stable per-worker busy duration
and park/unpark counts arrive in 1.45.0.
- Unstable spawned-task totals, combined park/unpark counts, and worker thread
IDs arrive in 1.39.0.
- Unstable H2 histogram configuration and renamed histogram APIs arrive in
1.41.0.
- Do not use
num_alive_tasks as an exact concurrent invariant; its samples
are not strongly consistent.
Read runtime-and-tasks.md for task hooks,
poll callbacks, task dumps, spawn locations, timers, and lifecycle ordering.
Synchronization quick reference
- Await
broadcast::Sender::closed() to stop producers after every receiver is
gone, and use broadcast::WeakSender when an observer must not keep the
channel open; both are available from 1.44.0.
- Use
mpsc::Receiver::blocking_recv_many from 1.41.0 for synchronous batched
receives.
- After
Receiver::close(), a drained try_recv() reports Disconnected from
1.43.4, except while outstanding permits can still send, where it reports
Empty from 1.47.5.
watch::Sender<T> implements Default when its value can be defaulted from
1.39.0.
- Tokio mpsc types satisfy unwind-safety bounds from 1.40.0.
Read synchronization.md before relying on close,
permit, wakeup, or fairness semantics.
I/O and networking quick reference
- Use
tokio::io::util::SimplexStream from 1.40.0 or
tokio_util::io::simplex from tokio-util 0.7.18.
- Name chained readers with public
tokio::io::Chain and inspect file buffer
limits with File::max_buf_size() from 1.48.0.
- Use Unix pipe endpoint
try_io and AioSource::register_borrowed from 1.52.0
for immediate pipe operations and borrowed AIO registration.
- Use
TcpStream::{quickack,set_quickack} from 1.48.0 and IPv6 TCLASS
support from 1.49.0 where supported by the target.
- Configure Unix child process groups with stable
Command::process_group from
1.40.0. Command::spawn_with arrives in 1.45.0 and accepts FnOnce from
1.48.0.
Consult the I/O and networking references for target support, backend details,
socket-address APIs, process races, and signal behavior.
Companion crate quick reference
- In
tokio-util, compose cancellation with run_until_cancelled, its owned
form, or FutureExt; cancellation wins a simultaneous-ready tie from 0.7.16.
- Use
AbortOnDropHandle from 0.7.12 and detach it from 0.7.16.
- Use stable
JoinMap from 0.7.16 and JoinQueue from 0.7.17.
- Recheck buffer assumptions:
Framed::with_capacity applies its capacity to
both read and write buffers from 0.7.16.
- In
tokio-stream, batch StreamMap output with next_many or
poll_next_many from 0.1.16, recover timed-chunk remainder with
ChunksTimeout::into_remainder from 0.1.18, and use meaningful receiver
stream size hints from 0.1.18.
Read tokio-util-and-stream.md for all
companion-crate features, fixes, and exact floors.
1---2name: tokio-knowledge-patch-23description: Tokio4license: MIT5---678# Tokio Knowledge Patch910Use this skill for version-sensitive Tokio work: dependency selection, runtime11construction, task behavior, channels, asynchronous I/O, networking, processes,12signals, and the companion `tokio-util` and `tokio-stream` crates. Check the13project manifest first and apply only guidance relevant to its pinned versions.1415## Reference index1617| Reference | Topics |18| --- | --- |19| [compatibility.md](references/compatibility.md) | Toolchain floors, safe patch releases, target support, and unstable configuration |20| [runtime-and-tasks.md](references/runtime-and-tasks.md) | Runtime construction, scheduling, task APIs, metrics, hooks, and diagnostics |21| [synchronization.md](references/synchronization.md) | `watch`, `broadcast`, `mpsc`, `oneshot`, `Notify`, semaphores, and `RwLock` |22| [io-and-filesystem.md](references/io-and-filesystem.md) | Async I/O types, files, pipes, AIO, io_uring, and standard output |23| [networking-process-signals.md](references/networking-process-signals.md) | Sockets, target-specific networking, child processes, and signals |24| [tokio-util-and-stream.md](references/tokio-util-and-stream.md) | Compatibility and APIs in `tokio-util` and `tokio-stream` |2526## Upgrade gates2728### Select safe patch releases2930- Use at least 1.42.1 when a `broadcast` channel may carry `Send` but `!Sync`31 values; 1.42.0 has an unsynchronized-clone soundness bug.32- On the 1.43 line, use 1.43.4 to include the pidfd, receiverless-broadcast,33 and closed-and-drained `mpsc::try_recv` corrections.34- Use at least 1.45.1 on `wasm32-unknown-unknown`; time-based metrics in 1.45.035 can make valid `Instant::now()` calls panic.36- Use at least 1.46.1 when task hooks inspect `TaskMeta::spawned_at` for tasks37 created with `tokio::spawn`.38- On the 1.47 line, use 1.47.5 for channel length, permit wakeup, outstanding39 permit, and `RwLock` limit behavior; 1.47.4 also fixes `recv_many` on a closed40 channel, and 1.47.2 fixes `join!`/`try_join!` hygiene.41- Use at least 1.51.1 when semaphore closure, Linux UDP pending errors, or42 cancellable io_uring opens matter.43- Do not remain on 1.52.0 when using `spawn_blocking`; require 1.52.1 to avoid a44 sharded blocking-queue hang.45- Use 1.53.1 for Windows signal support at the Rust 1.71 minimum and for the46 unstable alternate-timer cancellation race fix.4748See [compatibility.md](references/compatibility.md) for exact patch-line floors49and older-line backports.5051### Enforce compiler and dependency floors5253| Package | Minimum toolchain or dependency |54| --- | --- |55| Tokio from 1.39.0 | Rust 1.70 |56| Tokio from 1.48.0 | Rust 1.71 |57| `tokio-util` 0.7.12 | Rust 1.70 |58| `tokio-util` 0.7.17 | Rust 1.71 |59| `tokio-util` 0.7.18 | Tokio 1.44.0 |60| `tokio-stream` 0.1.16 | Rust 1.70 |6162### Adjust rejected or changed code6364- Put every standard-library socket into nonblocking mode before a Tokio65 `from_std` conversion; blocking sockets panic from 1.44.0 onward.6667```rust68let listener = std::net::TcpListener::bind(addr)?;69listener.set_nonblocking(true)?;70let listener = tokio::net::TcpListener::from_std(listener)?;71```7273- Keep `runtime::Builder::event_interval` nonzero; `event_interval(0)` panics74 from 1.50.0 onward.75- Keep blocking work out of futures and destructors polled or dropped by a76 `LocalSet` from 1.46.0 onward. Use `spawn_blocking` or move it outside.77- Replace deprecated `TcpStream::set_linger` and `TcpSocket::set_linger` calls.78 Use `TcpStream::set_zero_linger()` for abortive close from 1.50.0.79- Await, retain, or explicitly discard `JoinHandle::abort_handle()` and80 `Notify::notified()` results; their types are `#[must_use]`.81- Do not interpret a signal receive result of `None` as shutdown; signal82 listeners remain open from 1.50.0 onward.83- Expect task-owned state to be dropped before its `JoinHandle` completes from84 1.50.0 onward.85- Reuse or synchronize one Tokio standard-output handle when write ordering86 matters; independent handles may reorder writes.8788### Update unstable builds8990- Select `taskdump` and `io_uring` with Cargo features from 1.48.0; replace the91 former custom `--cfg` switches.92- Pass `LocalOptions` by value to unstable `Builder::build_local` from 1.46.0.93- Migrate off the removed unstable alternate multi-threaded runtime before94 using 1.45.0 or newer.95- Treat io_uring as opportunistic: Tokio may disable it after `EPERM`, and the96 operations available through the backend depend on the Tokio release.9798## Runtime and task quick reference99100### Choose local execution deliberately101102- Use stable `tokio::runtime::LocalRuntime` from 1.51.0 for thread-local103 `!Send` tasks. Earlier forms were unstable.104- The unstable macro flavor `#[tokio::main(flavor = "local")]` is available105 from 1.48.0.106- Use stable `runtime::id::Id` and `LocalSet::id()` from 1.49.0 for diagnostic107 identity.108- From 1.51.0, assign runtime names and use `runtime::worker_index()` for109 per-worker diagnostic context.110111### Preserve cooperative scheduling112113- `watch` receives and `broadcast::Receiver` participate in cooperative114 scheduling from 1.41.0.115- `select!` consumes cooperative budget from 1.44.0.116- Use `task::coop` for custom asynchronous resources from 1.44.0;117 `cooperative` and `poll_proceed` arrive in 1.47.0.118- `yield_now` takes effect immediately inside `block_in_place` from 1.42.0.119120### Use current task primitives121122- Use `tokio::sync::SetOnce` from 1.47.0 for asynchronously observable,123 single-assignment state.124- Use `Notify::notified_owned()` and `OwnedNotified` from 1.47.0 when the125 notification future must not borrow its `Notify`.126- Extend `JoinSet<T>` from an iterator from 1.49.0.127- Sort `task::Id` values or use them as ordered keys from 1.48.0.128- Use `LocalKey::try_get()` from 1.48.0 when missing task-local state should not129 panic.130131### Interpret metrics carefully132133- Stable global queue depth arrives in 1.41.0; stable per-worker busy duration134 and park/unpark counts arrive in 1.45.0.135- Unstable spawned-task totals, combined park/unpark counts, and worker thread136 IDs arrive in 1.39.0.137- Unstable H2 histogram configuration and renamed histogram APIs arrive in138 1.41.0.139- Do not use `num_alive_tasks` as an exact concurrent invariant; its samples140 are not strongly consistent.141142Read [runtime-and-tasks.md](references/runtime-and-tasks.md) for task hooks,143poll callbacks, task dumps, spawn locations, timers, and lifecycle ordering.144145## Synchronization quick reference146147- Await `broadcast::Sender::closed()` to stop producers after every receiver is148 gone, and use `broadcast::WeakSender` when an observer must not keep the149 channel open; both are available from 1.44.0.150- Use `mpsc::Receiver::blocking_recv_many` from 1.41.0 for synchronous batched151 receives.152- After `Receiver::close()`, a drained `try_recv()` reports `Disconnected` from153 1.43.4, except while outstanding permits can still send, where it reports154 `Empty` from 1.47.5.155- `watch::Sender<T>` implements `Default` when its value can be defaulted from156 1.39.0.157- Tokio mpsc types satisfy unwind-safety bounds from 1.40.0.158159Read [synchronization.md](references/synchronization.md) before relying on close,160permit, wakeup, or fairness semantics.161162## I/O and networking quick reference163164- Use `tokio::io::util::SimplexStream` from 1.40.0 or165 `tokio_util::io::simplex` from `tokio-util` 0.7.18.166- Name chained readers with public `tokio::io::Chain` and inspect file buffer167 limits with `File::max_buf_size()` from 1.48.0.168- Use Unix pipe endpoint `try_io` and `AioSource::register_borrowed` from 1.52.0169 for immediate pipe operations and borrowed AIO registration.170- Use `TcpStream::{quickack,set_quickack}` from 1.48.0 and IPv6 `TCLASS`171 support from 1.49.0 where supported by the target.172- Configure Unix child process groups with stable `Command::process_group` from173 1.40.0. `Command::spawn_with` arrives in 1.45.0 and accepts `FnOnce` from174 1.48.0.175176Consult the I/O and networking references for target support, backend details,177socket-address APIs, process races, and signal behavior.178179## Companion crate quick reference180181- In `tokio-util`, compose cancellation with `run_until_cancelled`, its owned182 form, or `FutureExt`; cancellation wins a simultaneous-ready tie from 0.7.16.183- Use `AbortOnDropHandle` from 0.7.12 and detach it from 0.7.16.184- Use stable `JoinMap` from 0.7.16 and `JoinQueue` from 0.7.17.185- Recheck buffer assumptions: `Framed::with_capacity` applies its capacity to186 both read and write buffers from 0.7.16.187- In `tokio-stream`, batch `StreamMap` output with `next_many` or188 `poll_next_many` from 0.1.16, recover timed-chunk remainder with189 `ChunksTimeout::into_remainder` from 0.1.18, and use meaningful receiver190 stream size hints from 0.1.18.191192Read [tokio-util-and-stream.md](references/tokio-util-and-stream.md) for all193companion-crate features, fixes, and exact floors.