It turns out that the CI job for testing `tokio_unstable` features isn't
actually running doctests for `tokio_unstable`, just lib and integration
tests. This is because RustDoc is responsible for running doctests, and
it needs the unstable cfg passed to it separately from `RUSTFLAGS`.
This means that if the examples for unstable APIs are broken, CI won't
catch this, which is not great!
This commit changes the `test-unstable` CI job to pass `--cfg
tokio_unstable` in `RUSTDOCFLAGS` as well as `RUSTFLAGS`. This way,
doctests for unstable APIs should actually run.
I also fixed a typo in one of the runtime metrics doctests that was
causing a compilation error, which was caught as a result of actually
testing the unstable API docs on CI. :)
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
Recent Clippy releases have added some new lints that trigger on some
code in Tokio. These aren't a big deal, but seeing them in my editor is
mildly annoying.
## Solution
This branch fixes the following issues flagged by Clippy:
* manual `Option::map` implementation
* use of `.map(...).flatten(...)` that could be replaced with
`.and_then(...)`
* manual implementation of saturating arithmetic on `Duration`s
* simplify some boolean expressions in assertions (`!res.is_ok()` can be
`res.is_err()`)
* fix redundant field names in initializers
* replace an unnecessary cast to `usize` with an explicitly typed
integer literal
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
Before we stabilize the `JoinSet` API, we intend to add a method for
individual tasks in the `JoinSet` to be aborted. Because the
`JoinHandle`s for the tasks spawned on a `JoinSet` are owned by the
`JoinSet`, the user can no longer use them to abort tasks on the
`JoinSet`. Therefore, we need another way to cause a remote abort of a
task on a `JoinSet` without holding its `JoinHandle`.
## Solution
This branch adds a new `AbortHandle` type in `tokio::task`, which
represents the owned permission to remotely cancel a task, but _not_ to
await its output. The `AbortHandle` type holds an additional reference
to the task cell.
A crate-private method is added to `JoinHandle` that returns an
`AbortHandle` for the same task, incrementing its ref count.
`AbortHandle` provides a single method, `AbortHandle::abort(self)`, that
remotely cancels the task. Dropping an `AbortHandle` decrements the
task's ref count but does not cancel it. The `AbortHandle` type is
currently marked as unstable.
The spawning methods on `JoinSet` are modified to return an
`AbortHandle` that can be used to cancel the spawned task.
## Future Work
- Currently, the `AbortHandle` type is _only_ available in the public
API through a `JoinSet`. We could also make the
`JoinHandle::abort_handle` method public, to allow users to use the
`AbortHandle` type in other contexts. I didn't do that in this PR,
because I wanted to make the API addition as minimal as possible, but we
could make this method public later.
- Currently, `AbortHandle` is not `Clone`. We could easily make it
`Clone` by incrementing the task's ref count. Since this adds more trait
impls to the API, we may want to be cautious about this, but I see no
obvious reason we would need to remove a `Clone` implementation if one
was added...
- There's been some discussion of adding a `JoinMap` type that allows
aborting tasks by key, and manages a hash map of keys to `AbortHandle`s,
and removes the tasks from the map when they complete. This would make
aborting by key much easier, since the user wouldn't have to worry about
keeping the state of the map of abort handles and the tasks actually
active on the `JoinSet` in sync. After thinking about it a bit, I
thought this is probably best as a `tokio-util` API --- it can currently
be implemented in `tokio-util` with the APIs added in `tokio` in this
PR.
- I noticed while working on this that `JoinSet::join_one` and
`JoinSet::poll_join_one` return a cancelled `JoinError` when a task is
cancelled. I'm not sure if I love this behavior --- it seems like it
would be nicer to just skip cancelled tasks and continue polling. But,
there are currently tests that expect a cancelled `JoinError` to be
returned for each cancelled task, so I didn't want to change it in
_this_ PR. I think this is worth revisiting before stabilizing the API,
though?
Signed-off-by: Eliza Weisman <eliza@buoyant.io>
## Motivation
Rust error messages seem to have changed a bit in 1.59.0
## Solution
Update the `trybuild` stderr output.
This should unbreak the tests on the latest Rust (and fix CI).
## Motivation
The `JoinSet` type is currently missing the `tokio_unstable` and
`feature = "rt"` `doc(cfg(...))` attributes, making it erroneously
appear to be available without the required feature and without unstable
features enabled. This is incorrect.
I believe this is because `doc(cfg(...))` on a re-export doesn't
actually add the required cfgs to the type itself, and the
`cfg_unstable!` is currently only guarding a re-export and module.
## Solution
This PR fixes the missing attributes.
## Motivation
PR #4499 made the `JoinSet` API unstable, but did not add a
documentation note explaining unstable features. In general, since the
docs.rs build includes unstable APIs, it's probably worth including
these notes so that users understand what it means for an API to be
unstable.
## Solution
This branch adds a note on unstable APIs to the `JoinSet` type-level
documentation, similar to the notes for `task::Builder` and the runtime
metrics APIs.
Also, I noticed that there was a broken link to the top-level
documentation on unstable APIs in the docs for `task::Builder`, so I
fixed that as well.
time: resolve TODO
## Motivation
Existing `TODO` comment in `src/time/driver/wheel/level.rs`.
## Solution
`level_range()` always return a strictly positive power of 2. If `b` is a
strictly positive power of 2, `a - (a % b)` is equal to `a & !(b - 1)`.
The major breaking change in Mio v0.8 is TcpSocket type being removed.
Replacing Mio's TcpSocket we switch to the socket2 library which
provides a similar type Socket, as well as SockRef, which provide all
options TcpSocket provided (and more!).
Tokio's TcpSocket type is now backed by Socket2 instead of Mio's
TcpSocket. The main pitfall here is that socket2 isn't non-blocking by
default, which Mio obviously is. As a result we have to do potentially
blocking calls more carefully, specifically we need to handle
would-block-like errors when connecting the TcpSocket ourselves.
One benefit for this change is that adding more socket options to
TcpSocket is now merely a single function call away (in most cases
anyway).
PR #3881 factored out the spawning of local tasks on a `LocalSet` into a
function `spawn_local_inner`, so that the implementation could be shared
with the `task::Builder` API. But, that PR neglected to add a
`#[track_caller]` attribute to `spawn_local_inner`, so the `tracing`
spans for local tasks are all generated with `spawn_local_inner` as
their spawn location, rather than forwarding the actual spawn location
from the calling function.
This causes pretty useless results when using `tokio-console` with code
that spawns a number of local tasks, such as Actix
(https://reddit.com/r/rust/comments/snt5fq/can_tokioconsole_profile_actixrt/)
This commit fixes the issue by adding the missing `#[track_caller]`
attribute.