The broadcast channel allows multiple senders to send messages to
multiple receivers, where each receiver receives messages starting from
when it subscribes. After all senders are dropped, the receivers will
continue to receive all waiting messages in the buffer and then receive
a `Closed` error.
To mark that a channel has closed, it stores two closed flags, one on
the channel level and another in the buffer slot *after* the last used
slot (this may also be the earliest entry being kept for lagged
receivers, see #2425).
However, we don't need both closed flags, keeping the channel level
closed flag is sufficient.
Without the slot level closed flag, each receiver receives each message
until it is up to date and for that receiver the channel is empty. Then,
the actual return message is chosen depending on the channel level
closed flag; if the channel is NOT closed, then `Empty` is returned, if
the channel is closed then `Closed` is returned instead.
With the modified logic, there is no longer a need to append a closed
token to the internal buffer (by setting the slot level closed flag on
the next slot). This fixes the off by one error described in #4814,
which caused a receiver which was created after the channel was already
closed to get `Empty` from `try_recv` (or hang forever when calling
`recv`) instead of receiving `Closed`.
As a bonus, we save a single `bool` on each buffer slot.
Refs: #4814
The contribution guide describes the Tokio code of conduct and gives a
list of steps to follow when contributing in different ways. In the
guide to contributing a pull request, commands are listed to be run by
the contributor locally to help ensure that the PR will pass on CI.
The command to run clippy isn't the same as the one run on CI,
specifically the command doesn't check the tests. This commit changes
the command to match the one on CI, so that tests are checked by clippy
as well.
As the [epoll documentation points out](https://man7.org/linux/man-pages/man7/epoll.7.html), a read that only partially fills a buffer is sufficient to show that the socket buffer has been drained.
We can take advantage of this by clearing readiness in this case, which seems to significantly improve performance under certain conditions.
Co-authored-by: Carl Lerche <me@carllerche.com>
The documentation for the runtime `Builder::worker_threads` function
incorrectly stated that it would panic if used when constructing a
`current_thread` runtime. In truth, the call to the function has no
effect.
Since adding the described panic to the code could cause new panics in
existing code using tokio, the documentation has been modified to
describe the existing behavior.
Refs: #4773
This change adds a case that was missing from the original PR, #4793.
The `io::driver::Handle::current` function was only covered by
`#[track_caller]` in the case that the `rt` feature is enabled, however
it was missing in the case that the `rt` feture isn't enabled (in which
case a panic would be more common).
This particular case cannot be tested in the tokio tests as they always
run with all features enabled.
Refs: #4413
Functions that may panic can be annotated with `#[track_caller]` so that
in the event of a panic, the function where the user called the
panicking function is shown instead of the file and line within Tokio
source.
This change adds `#[track_caller]` to all the public APIs in the task
module of the tokio crate where the documentation describes how the
function may panic due to incorrect context or inputs.
In cases where `#[track_caller]` does not work, it has been left out.
For example, it currently does not work on async functions, blocks, or
closures. So any call stack that passes through one of these before
reaching the actual panic is not able to show the calling site outside
of tokio as the panic location.
The following functions have call stacks that pass through closures:
* `task::block_in_place`
* `task::local::spawn_local`
Tests are included to cover each potentially panicking function.
The following functions already had `#[track_caller]` applied everywhere
it was needed and only tests have been added:
* `task::spawn`
* `task::LocalKey::sync_scope`
Refs: #4413
Functions that may panic can be annotated with #[track_caller] so that
in the event of a panic, the function where the user called the
panicking function is shown instead of the file and line within Tokio
source.
This change adds #[track_caller] to all the non-unstable public net APIs
in the main tokio crate where the documentation describes how the
function may panic due to incorrect context or inputs. Not all panic
cases can have #[track_caller] applied fully as the callstack passes
through a closure which isn't yet supported by the annotation (e.g. net
functions called from outside a tokio runtime).
Additionally, the documentation was updated to indicate additional cases
in which the public net functions may panic (the same as the io
functions).
Tests are included to cover each potentially panicking function.
Refs: #4413
This adds initial, unstable, support for the wasm32-wasi target. Not all of Tokio's
features are supported yet as WASI's non-blocking APIs are still limited.
Refs: tokio-rs/tokio#4827
Currently, we only have WASM regression tests that run without WASI.
However, rust provides a WASI specific target which enables code to
special case WASI. This PR adds a basic test to cover that case.
This is an initial addition to help land tokio-rs/tokio#4716.
Functions that may panic can be annotated with `#[track_caller]` so that
in the event of a panic, the function where the user called the
panicking function is shown instead of the file and line within Tokio
source.
This change adds `#[track_caller]` to all the public APIs in the sync
module of the tokio crate where the documentation describes how the
function may panic due to incorrect context or inputs.
In cases where `#[track_caller]` does not work, it has been left out.
For example, it currently does not work on async functions, blocks, or
closures. So any call stack that passes through one of these before
reaching the actual panic is not able to show the calling site outside
of tokio as the panic location.
The following functions have call stacks that pass through closures:
* `sync:⌚:Sender::send_modify`
* `sync:⌚:Sender::send_if_modified`
Additionally, in the above functions it is a panic inside the supplied
closure which causes the function to panic, and so showing the location
of the panic itself is desirable.
The following functions are async:
* `sync::mpsc::bounded::Sender::send_timeout`
Tests are included to cover each potentially panicking function.
Refs: #4413
Functions that may panic can be annotated with #[track_caller] so that
in the event of a panic, the function where the user called the
panicking function is shown instead of the file and line within Tokio
source.
This change adds #[track_caller] to the signal() function which is the
only function in the signal public API which can panic. Documentation
was added to this function to indicate that it may panic.
Not all panic cases can have #[track_caller] applied fully as the
callstack passes through a closure which isn't yet supported by the
annotation (e.g. signal() called from outside a tokio runtime).
Tests are included to cover the case where signal() is called from a
runtime without IO enabled.
Refs: #4413
This fixes#4801, where, as a result of https://github.com/rust-lang/rust/pull/95469, our implementation of cat used for this test no longer works, as stdio functions on windows now can abort the process if the pipe is set to nonblocking mode.
Unfortunately in windows, setting one end of the pipe to be nonblocking makes the whole thing nonblocking, so when, in tokio::process we set the child pipes to nonblocking mode, it causes serious problems for any rust program at the other end.
Fixing this issue is for another day, but fixing the tests is for today.