Tokio Knowledge Patch
Use this patch when upgrading Tokio, selecting a safe patch release, or writing
version-sensitive runtime, synchronization, I/O, networking, process, signal,
tokio-util, or tokio-stream code. Check the detailed topic reference before
depending on unstable APIs or patch-level fixes.
Reference index
| Reference |
Topics |
| compatibility.md |
Rust and dependency floors, safe patch releases, build configuration, target support |
| runtime-and-tasks.md |
Runtime construction, local execution, task APIs, scheduling, hooks, metrics, tracing |
| synchronization.md |
watch, broadcast, mpsc, oneshot, Notify, semaphores, permits, and single-assignment state |
| io-and-filesystem.md |
Async I/O types, files, pipes, AIO, io_uring filesystem support, and standard output |
| networking-process-signals.md |
Sockets, networking targets, child processes, and signals |
| tokio-util-and-stream.md |
Companion-crate dependency floors, task utilities, codecs, cancellation, and stream adapters |
Breaking changes and upgrade gates
Select safe patch releases
- Use at least 1.42.1 when a
broadcast channel can carry a Send but !Sync
value; 1.42.0 clones such values without synchronization.
- On the 1.43 line, use at least 1.43.2 for pidfd-backed child waiting, 1.43.3
for receiverless
broadcast::Sender state, and 1.43.4 for closed-and-drained
mpsc::Receiver::try_recv behavior.
- Use at least 1.45.1 on
wasm32-unknown-unknown; 1.45.0 can panic when
time-based metrics call Instant::now().
- 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.2 for
join!/try_join! macro hygiene, 1.47.4
for closed-channel recv_many, and 1.47.5 for corrected mpsc length, permit
wakeups, outstanding-permit state, and nonzero RwLock reader limits.
- Use at least 1.51.1 when semaphore closure after forgotten permits, Linux UDP
pending errors, or cancelled io_uring opens matter.
- Do not remain on 1.52.0 when using
spawn_blocking; use at least 1.52.1 to
avoid the sharded blocking-queue hang.
- Use 1.51.4 or 1.52.4 when a
before_park callback can schedule work, so the
runtime does not skip the driver.
- Use 1.53.1 for Tokio signal support on Windows with the Rust 1.71 toolchain;
1.53.0 accidentally used a newer standard-library API.
See compatibility.md for the complete upgrade
and target matrix.
Enforce compiler and dependency floors
| Package floor |
Requirement |
| Tokio 1.39.0 |
Rust 1.70 or newer |
| Tokio 1.48.0 |
Rust 1.71 or newer |
tokio-util 0.7.12 |
Rust 1.70 or newer |
tokio-util 0.7.17 |
Rust 1.71 or newer |
tokio-util 0.7.18 |
Tokio 1.44.0 or newer |
tokio-stream 0.1.13 |
Rust 1.56 or newer |
tokio-stream 0.1.15 |
Rust 1.63 or newer |
tokio-stream 0.1.16 |
Rust 1.70 or newer |
tokio-stream 0.1.14 |
Tokio 1.15 or newer |
Adjust rejected or changed code
- Put standard-library sockets into nonblocking mode before any Tokio
from_std conversion. Since 1.44.0, passing a blocking socket panics.
let listener = std::net::TcpListener::bind("127.0.0.1:0")?;
listener.set_nonblocking(true)?;
let listener = tokio::net::TcpListener::from_std(listener)?;
- Keep
runtime::Builder::event_interval nonzero; passing 0 panics as of
1.50.0.
- Keep in-place blocking operations out of futures and destructors driven by a
LocalSet as of 1.46.0. Move blocking work to spawn_blocking.
- Replace deprecated
TcpStream::set_linger and TcpSocket::set_linger calls.
Use TcpStream::set_zero_linger() from 1.50.0 for abortive close behavior.
- Await, retain, or explicitly discard
JoinHandle::abort_handle() and
Notify::notified() results; their types are #[must_use] as of 1.40.0 and
1.41.0 respectively.
- Do not interpret signal-stream
None as shutdown. Signal listeners remain
open as of 1.50.0; arrange explicit cancellation.
- Expect task-owned state to be dropped before its
JoinHandle completes as of
1.50.0.
- Expect a panicked task's formatted
JoinError to include the panic message
as of 1.40.0.
- Reuse or synchronize one Tokio standard-output handle when write ordering
matters; multiple handles can reorder writes.
Update unstable configuration
- Select
taskdump and io_uring with Cargo features as of 1.48.0, replacing
their former custom --cfg switches.
- Pass
LocalOptions by value to runtime::Builder::build_local as of 1.46.0.
- Migrate away from the removed unstable alternate multi-threaded runtime as of
1.45.0.
- Treat io_uring as opportunistic: Tokio disables it on
EPERM, and later
filesystem operations remain explicitly unstable.
Runtime and task quick reference
Choose local execution deliberately
- Use stable
tokio::runtime::LocalRuntime from 1.51.0 for local task
execution. It first appeared as unstable in 1.41.0.
- With unstable APIs on 1.48.0, use
#[tokio::main(flavor = "local")] for a
macro-created local runtime.
- Use stable
runtime::id::Id and LocalSet::id() from 1.49.0 to identify
runtimes and local sets.
- From 1.51.0, assign runtime names and call
tokio::runtime::worker_index() for per-worker diagnostic context.
Preserve cooperative scheduling
watch receives and broadcast::Receiver participate in cooperative
scheduling as of 1.41.0.
select! consumes cooperative task budget as of 1.44.0.
- Use
task::coop for custom resources from 1.44.0; cooperative and
poll_proceed are available from 1.47.0.
yield_now takes effect immediately inside block_in_place as of 1.42.0.
Use task and runtime instrumentation
- Stable
RuntimeMetrics::global_queue_depth and task Id APIs arrive in
1.41.0.
- Stable per-worker busy duration and park/unpark counts arrive in 1.45.0.
- Unstable spawned-task totals, combined worker park/unpark counts, and worker
thread IDs arrive in 1.39.0.
- The runtime metrics API adds task schedule latency in 1.53.0.
- Do not use
num_alive_tasks as an exact concurrent invariant; samples are
not strongly consistent as of 1.49.0.
Read runtime-and-tasks.md for lifecycle and
poll hooks, tracing, task dumps, caller-aware timeouts, and driver handoff.
Synchronization quick reference
- 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 a
notification future must not borrow its Notify.
- Await
broadcast::Sender::closed() from 1.44.0 to stop a producer after all
receivers disappear; use broadcast::WeakSender when an observer must not
keep the channel open.
- Use
mpsc::Receiver::blocking_recv_many from 1.41.0 for blocking batched
receives.
- Derive
Default for state containing watch::Sender<T> as of 1.39.0 when
T satisfies the implementation's bounds.
- Use Tokio mpsc values across unwind-safety bounds as of 1.40.0.
Read synchronization.md before depending on
close, permit, wakeup, or fairness semantics.
I/O, networking, process, and signal quick reference
I/O and files
- Use
io::util::SimplexStream from 1.40.0, or
tokio_util::io::simplex from tokio-util 0.7.18.
- Use public
tokio::io::Chain from 1.48.0 when a chained reader's concrete
type must be named. From 1.53.0, a zero-length read no longer advances it.
- Inspect a file's buffer limit with
File::max_buf_size() from 1.48.0; file
clones preserve that limit.
- Convert
OwnedFd or OwnedHandle directly into tokio::fs::File from
1.53.0.
- Use Unix pipe
try_io and AioSource::register_borrowed from 1.52.0 for
immediate pipe operations and borrowed AIO registration.
Networking, processes, and signals
- Use Unix
SocketAddr conversions from 1.41.0 and
as_abstract_name() from 1.48.0; 1.53.0 expands its inspection methods.
- Use
TcpStream::{quickack,set_quickack} from 1.48.0 where TCP quick
acknowledgements are exposed, and configure IPv6 TCLASS from 1.49.0.
- Require 1.46.0 when successful macOS
TcpStream::shutdown matters.
- Configure Unix child process groups with stable
Command::process_group
from 1.40.0.
- Use
Command::spawn_with from 1.45.0; its callback may consume captured
values through FnOnce as of 1.48.0.
- Treat
Child::start_kill() after normal exit as a successful cleanup race as
of 1.44.0.
Read io-and-filesystem.md and
networking-process-signals.md for
backend behavior and target-specific support.
Companion-crate quick reference
tokio-util
- Compose cancellation with
run_until_cancelled, its owned form, or
FutureExt adapters; 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 capacity assumptions: from 0.7.16,
Framed::with_capacity applies
its capacity to the read buffer too.
tokio-stream
- Use
WatchStream::from_changes from 0.1.12 to skip the current value and
wait for later watch-channel changes.
- Batch
StreamMap results with next_many or poll_next_many from 0.1.16.
- Recover an incomplete timed chunk with
ChunksTimeout::into_remainder from
0.1.18.
- Use meaningful receiver-stream
size_hint bounds from 0.1.18.
Read tokio-util-and-stream.md for all
companion-crate behavior and release floors.
1---2name: tokio-knowledge-patch3description: Tokio4license: MIT5---678# Tokio Knowledge Patch910Use this patch when upgrading Tokio, selecting a safe patch release, or writing11version-sensitive runtime, synchronization, I/O, networking, process, signal,12`tokio-util`, or `tokio-stream` code. Check the detailed topic reference before13depending on unstable APIs or patch-level fixes.1415## Reference index1617| Reference | Topics |18| --- | --- |19| [compatibility.md](references/compatibility.md) | Rust and dependency floors, safe patch releases, build configuration, target support |20| [runtime-and-tasks.md](references/runtime-and-tasks.md) | Runtime construction, local execution, task APIs, scheduling, hooks, metrics, tracing |21| [synchronization.md](references/synchronization.md) | `watch`, `broadcast`, `mpsc`, `oneshot`, `Notify`, semaphores, permits, and single-assignment state |22| [io-and-filesystem.md](references/io-and-filesystem.md) | Async I/O types, files, pipes, AIO, io_uring filesystem support, and standard output |23| [networking-process-signals.md](references/networking-process-signals.md) | Sockets, networking targets, child processes, and signals |24| [tokio-util-and-stream.md](references/tokio-util-and-stream.md) | Companion-crate dependency floors, task utilities, codecs, cancellation, and stream adapters |2526## Breaking changes and upgrade gates2728### Select safe patch releases2930- Use at least 1.42.1 when a `broadcast` channel can carry a `Send` but `!Sync`31 value; 1.42.0 clones such values without synchronization.32- On the 1.43 line, use at least 1.43.2 for pidfd-backed child waiting, 1.43.333 for receiverless `broadcast::Sender` state, and 1.43.4 for closed-and-drained34 `mpsc::Receiver::try_recv` behavior.35- Use at least 1.45.1 on `wasm32-unknown-unknown`; 1.45.0 can panic when36 time-based metrics call `Instant::now()`.37- Use at least 1.46.1 when task hooks inspect `TaskMeta::spawned_at` for tasks38 created with `tokio::spawn`.39- On the 1.47 line, use 1.47.2 for `join!`/`try_join!` macro hygiene, 1.47.440 for closed-channel `recv_many`, and 1.47.5 for corrected mpsc length, permit41 wakeups, outstanding-permit state, and nonzero `RwLock` reader limits.42- Use at least 1.51.1 when semaphore closure after forgotten permits, Linux UDP43 pending errors, or cancelled io_uring opens matter.44- Do not remain on 1.52.0 when using `spawn_blocking`; use at least 1.52.1 to45 avoid the sharded blocking-queue hang.46- Use 1.51.4 or 1.52.4 when a `before_park` callback can schedule work, so the47 runtime does not skip the driver.48- Use 1.53.1 for Tokio signal support on Windows with the Rust 1.71 toolchain;49 1.53.0 accidentally used a newer standard-library API.5051See [compatibility.md](references/compatibility.md) for the complete upgrade52and target matrix.5354### Enforce compiler and dependency floors5556| Package floor | Requirement |57| --- | --- |58| Tokio 1.39.0 | Rust 1.70 or newer |59| Tokio 1.48.0 | Rust 1.71 or newer |60| `tokio-util` 0.7.12 | Rust 1.70 or newer |61| `tokio-util` 0.7.17 | Rust 1.71 or newer |62| `tokio-util` 0.7.18 | Tokio 1.44.0 or newer |63| `tokio-stream` 0.1.13 | Rust 1.56 or newer |64| `tokio-stream` 0.1.15 | Rust 1.63 or newer |65| `tokio-stream` 0.1.16 | Rust 1.70 or newer |66| `tokio-stream` 0.1.14 | Tokio 1.15 or newer |6768### Adjust rejected or changed code6970- Put standard-library sockets into nonblocking mode before any Tokio71 `from_std` conversion. Since 1.44.0, passing a blocking socket panics.7273```rust74let listener = std::net::TcpListener::bind("127.0.0.1:0")?;75listener.set_nonblocking(true)?;76let listener = tokio::net::TcpListener::from_std(listener)?;77```7879- Keep `runtime::Builder::event_interval` nonzero; passing `0` panics as of80 1.50.0.81- Keep in-place blocking operations out of futures and destructors driven by a82 `LocalSet` as of 1.46.0. Move blocking work to `spawn_blocking`.83- Replace deprecated `TcpStream::set_linger` and `TcpSocket::set_linger` calls.84 Use `TcpStream::set_zero_linger()` from 1.50.0 for abortive close behavior.85- Await, retain, or explicitly discard `JoinHandle::abort_handle()` and86 `Notify::notified()` results; their types are `#[must_use]` as of 1.40.0 and87 1.41.0 respectively.88- Do not interpret signal-stream `None` as shutdown. Signal listeners remain89 open as of 1.50.0; arrange explicit cancellation.90- Expect task-owned state to be dropped before its `JoinHandle` completes as of91 1.50.0.92- Expect a panicked task's formatted `JoinError` to include the panic message93 as of 1.40.0.94- Reuse or synchronize one Tokio standard-output handle when write ordering95 matters; multiple handles can reorder writes.9697### Update unstable configuration9899- Select `taskdump` and `io_uring` with Cargo features as of 1.48.0, replacing100 their former custom `--cfg` switches.101- Pass `LocalOptions` by value to `runtime::Builder::build_local` as of 1.46.0.102- Migrate away from the removed unstable alternate multi-threaded runtime as of103 1.45.0.104- Treat io_uring as opportunistic: Tokio disables it on `EPERM`, and later105 filesystem operations remain explicitly unstable.106107## Runtime and task quick reference108109### Choose local execution deliberately110111- Use stable `tokio::runtime::LocalRuntime` from 1.51.0 for local task112 execution. It first appeared as unstable in 1.41.0.113- With unstable APIs on 1.48.0, use `#[tokio::main(flavor = "local")]` for a114 macro-created local runtime.115- Use stable `runtime::id::Id` and `LocalSet::id()` from 1.49.0 to identify116 runtimes and local sets.117- From 1.51.0, assign runtime names and call118 `tokio::runtime::worker_index()` for per-worker diagnostic context.119120### Preserve cooperative scheduling121122- `watch` receives and `broadcast::Receiver` participate in cooperative123 scheduling as of 1.41.0.124- `select!` consumes cooperative task budget as of 1.44.0.125- Use `task::coop` for custom resources from 1.44.0; `cooperative` and126 `poll_proceed` are available from 1.47.0.127- `yield_now` takes effect immediately inside `block_in_place` as of 1.42.0.128129### Use task and runtime instrumentation130131- Stable `RuntimeMetrics::global_queue_depth` and task `Id` APIs arrive in132 1.41.0.133- Stable per-worker busy duration and park/unpark counts arrive in 1.45.0.134- Unstable spawned-task totals, combined worker park/unpark counts, and worker135 thread IDs arrive in 1.39.0.136- The runtime metrics API adds task schedule latency in 1.53.0.137- Do not use `num_alive_tasks` as an exact concurrent invariant; samples are138 not strongly consistent as of 1.49.0.139140Read [runtime-and-tasks.md](references/runtime-and-tasks.md) for lifecycle and141poll hooks, tracing, task dumps, caller-aware timeouts, and driver handoff.142143## Synchronization quick reference144145- Use `tokio::sync::SetOnce` from 1.47.0 for asynchronously observable146 single-assignment state.147- Use `Notify::notified_owned()` and `OwnedNotified` from 1.47.0 when a148 notification future must not borrow its `Notify`.149- Await `broadcast::Sender::closed()` from 1.44.0 to stop a producer after all150 receivers disappear; use `broadcast::WeakSender` when an observer must not151 keep the channel open.152- Use `mpsc::Receiver::blocking_recv_many` from 1.41.0 for blocking batched153 receives.154- Derive `Default` for state containing `watch::Sender<T>` as of 1.39.0 when155 `T` satisfies the implementation's bounds.156- Use Tokio mpsc values across unwind-safety bounds as of 1.40.0.157158Read [synchronization.md](references/synchronization.md) before depending on159close, permit, wakeup, or fairness semantics.160161## I/O, networking, process, and signal quick reference162163### I/O and files164165- Use `io::util::SimplexStream` from 1.40.0, or166 `tokio_util::io::simplex` from `tokio-util` 0.7.18.167- Use public `tokio::io::Chain` from 1.48.0 when a chained reader's concrete168 type must be named. From 1.53.0, a zero-length read no longer advances it.169- Inspect a file's buffer limit with `File::max_buf_size()` from 1.48.0; file170 clones preserve that limit.171- Convert `OwnedFd` or `OwnedHandle` directly into `tokio::fs::File` from172 1.53.0.173- Use Unix pipe `try_io` and `AioSource::register_borrowed` from 1.52.0 for174 immediate pipe operations and borrowed AIO registration.175176### Networking, processes, and signals177178- Use Unix `SocketAddr` conversions from 1.41.0 and179 `as_abstract_name()` from 1.48.0; 1.53.0 expands its inspection methods.180- Use `TcpStream::{quickack,set_quickack}` from 1.48.0 where TCP quick181 acknowledgements are exposed, and configure IPv6 `TCLASS` from 1.49.0.182- Require 1.46.0 when successful macOS `TcpStream::shutdown` matters.183- Configure Unix child process groups with stable `Command::process_group`184 from 1.40.0.185- Use `Command::spawn_with` from 1.45.0; its callback may consume captured186 values through `FnOnce` as of 1.48.0.187- Treat `Child::start_kill()` after normal exit as a successful cleanup race as188 of 1.44.0.189190Read [io-and-filesystem.md](references/io-and-filesystem.md) and191[networking-process-signals.md](references/networking-process-signals.md) for192backend behavior and target-specific support.193194## Companion-crate quick reference195196### `tokio-util`197198- Compose cancellation with `run_until_cancelled`, its owned form, or199 `FutureExt` adapters; cancellation wins a simultaneous-ready tie from200 0.7.16.201- Use `AbortOnDropHandle` from 0.7.12 and detach it from 0.7.16.202- Use stable `JoinMap` from 0.7.16 and `JoinQueue` from 0.7.17.203- Recheck capacity assumptions: from 0.7.16, `Framed::with_capacity` applies204 its capacity to the read buffer too.205206### `tokio-stream`207208- Use `WatchStream::from_changes` from 0.1.12 to skip the current value and209 wait for later watch-channel changes.210- Batch `StreamMap` results with `next_many` or `poll_next_many` from 0.1.16.211- Recover an incomplete timed chunk with `ChunksTimeout::into_remainder` from212 0.1.18.213- Use meaningful receiver-stream `size_hint` bounds from 0.1.18.214215Read [tokio-util-and-stream.md](references/tokio-util-and-stream.md) for all216companion-crate behavior and release floors.