-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add Interest::PRIORITY and ready and ready_mut functions to AsyncFd #5566
Conversation
I'm seeing a weird CI error here, that seems unrelated to the changes that are made. My other PR for which CI ran recently has the same problem
So I'm assuming this is because I rebased on current master? CI Output
|
I have no idea what's up with the CI issue is, but it isn't your fault. |
Would it be possible to add a test for this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how/if this should be tested in tokio itself
Perhaps you can take a look how mio tests POLLPRI and add a similar test using types from Tokio.
4cfe812
to
8302636
Compare
As a general note, I'm happy that you're taking a stab at this. It has been a long-standing issue. |
I'm happy to, this was a fun journey into the depths of tokio and mio (something I'd wanted to do for a while). I think I added |
eec6959
to
a2a6f7e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, but I would like a +1 from @Darksonn as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have done something similar to your work here, but mine is not as "production ready" as your work. It is very well done. Thank you.
You can have a look at my code here: https://github.com/poeschel/tokio/tree/interest_prio
One thing I did differently is, I added direct priority support to the tokio TcpStream
. This is maybe worth pulling in here. Priority support for the TcpStream
also was in mio version 0.8.6.
And the other thing I did differently is I added a new waker for priority. (which then implies to also add the Direction::Prioriry
(which sounds weird)). I thought about this and I am also not shure if it is right. But I think it is. If you have some events in the ready queue and then a priority event arrives, you want this to be handled indepently of the read events, right? This is what "priority" is for, isn't it?
Regarding a test for |
Eh, maybe not. We wouldn't be able to test that in CI. However, I would like to know whether anyone has tried running the code and seen it work at least once for a sanity check. |
I can test my use-case and the unit tests I wrote for my fork on this code tomorrow. |
@@ -191,6 +227,11 @@ cfg_io_readiness! { | |||
ready |= Ready::WRITE_CLOSED; | |||
} | |||
|
|||
#[cfg(any(target_os = "linux", target_os = "android"))] | |||
if interest.is_priority() { | |||
ready |= Ready::PRIORITY; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note for the future: if we add the Ready::READ_CLOSED
to mask
above, we should also add it here
thanks for your input @poeschel! re. pulling in more stuff: I'm open to it, but also think a separate later PR would be fine. |
As promised, I tested today with my unit test and gpio sysfs in linux and my real world use-case with video4linux and both do work in principle. But I think we really should have a seperate worker for priority events:
I think it is better to add a seperate priority waker, or am I missing something? |
You are right! This is about AsyncFd here. The TcpStream can be another PR. |
Adding a separate waker for priority events makes sense to me. |
@poeschel I've been looking at this. One thing I don't see is how the current example would use this new priority direction/waker. You seem to be using it in a custom what are the consequences of adding the custom waker for the functionality in this PR so far? or is it really a primitive that is needed for e.g. TCP? |
I'm not following this. Tokio has a It may be that |
here's what I understand: Because we don't have async traits, traits that deal with async often have functions that return impl Stream for AsyncV4l2EventHandle {
type Item = io::Result<i32>;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
loop {
let blah = self.asyncfd.poll_priority_ready_mut(cx);
let mut guard = ready!(blah)?;
let res = guard.try_io(|inner| inner.get_mut().get_event());
guard.clear_ready();
match res {
Err(TryIoError { .. }) => {
continue;
},
Ok(Ok(event)) => {
return Poll::Ready(Some(Ok(event)));
},
Ok(Err(err)) => {
return Poll::Ready(Some(Err(err.into())));
}
}
}
}
} The
There is nowhere to pin a future in that impl (right?) So assuming that we want impl AsyncFd<T> {
pub fn poll_read_ready_mut<'a>(
&'a mut self,
cx: &mut Context<'_>,
) -> Poll<io::Result<AsyncFdReadyMutGuard<'a, T>>> {
let event = ready!(self.registration.poll_read_ready(cx))?;
Ok(AsyncFdReadyMutGuard {
async_fd: self,
event: Some(event),
})
.into()
}
}
...
impl Registration {
// Uses the poll path, requiring the caller to ensure mutual exclusion for
// correctness. Only the last task to call this function is notified.
pub(crate) fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<ReadyEvent>> {
self.poll_ready(cx, Direction::Read)
}
} so working by analogy, we need some The above makes sense to me, and the conclusion seems to be that for correct behavior, an extra waker for priority events is needed. But maybe I'm missing something here? |
026a41d
to
fc0b2af
Compare
To avoid the waker issue, I would not expose priority via a "poll" method. The async fns do not need a waker per readiness type. You can always convert a future returned by an |
It seems to me the key issue here is Then, we can add "priority" to |
this PR already adds
which is follows the pattern of
and then adds a implementing The I'm not sure how boxing helps in the example above. The problem is that there is no way to hold on to a future between calls to
but the call to all in all, I'd suggest that we declare polling out-of-scope for this PR, and focus just on the two functions from the title, |
priority is really a special kind of read; we want to know when no more data will come
it only uses the readable and writable interests. AsyncFd::with_interest can be used for e.g. the priority interest, or for exclusively read or write readiness.
ready really the old readiness function, which has now been made public and renamed to just `ready` for consistency with e.g. TcpStream
it is important to clear only the readiness corresponding to an operation that was actually observed to block, especially when using combined interests
3cec780
to
81cb2bb
Compare
wasm/wasi CI fails with
which is weird. In the |
The mio issue has been fixed upstream. I reran ci and it should pass now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One nit, otherwise LGTM.
Co-authored-by: Alice Ryhl <aliceryhl@google.com>
Awesome, thanks for the work! |
thanks for all the review/help, I really like where this ended up! |
Also, thank you very much from my side for your work! |
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [tokio](https://tokio.rs) ([source](https://github.com/tokio-rs/tokio)) | dependencies | minor | `1.28.2` -> `1.29.1` | | [tokio](https://tokio.rs) ([source](https://github.com/tokio-rs/tokio)) | dev-dependencies | minor | `1.28.2` -> `1.29.1` | --- ### Release Notes <details> <summary>tokio-rs/tokio (tokio)</summary> ### [`v1.29.1`](https://github.com/tokio-rs/tokio/releases/tag/tokio-1.29.1): Tokio v1.29.1 [Compare Source](tokio-rs/tokio@tokio-1.29.0...tokio-1.29.1) ##### Fixed - rt: fix nesting two `block_in_place` with a `block_on` between (#​5837]) #​5837]: tokio-rs/tokio#5837 ### [`v1.29.0`](https://github.com/tokio-rs/tokio/releases/tag/tokio-1.29.0): Tokio v1.29.0 [Compare Source](tokio-rs/tokio@tokio-1.28.2...tokio-1.29.0) Technically a breaking change, the `Send` implementation is removed from `runtime::EnterGuard`. This change fixes a bug and should not impact most users. ##### Breaking - rt: `EnterGuard` should not be `Send` (#​5766]) ##### Fixed - fs: reduce blocking ops in `fs::read_dir` (#​5653]) - rt: fix possible starvation (#​5686], #​5712]) - rt: fix stacked borrows issue in `JoinSet` (#​5693]) - rt: panic if `EnterGuard` dropped incorrect order (#​5772]) - time: do not overflow to signal value (#​5710]) - fs: wait for in-flight ops before cloning `File` (#​5803]) ##### Changed - rt: reduce time to poll tasks scheduled from outside the runtime (#​5705], #​5720]) ##### Added - net: add uds doc alias for unix sockets (#​5659]) - rt: add metric for number of tasks (#​5628]) - sync: implement more traits for channel errors (#​5666]) - net: add nodelay methods on TcpSocket (#​5672]) - sync: add `broadcast::Receiver::blocking_recv` (#​5690]) - process: add `raw_arg` method to `Command` (#​5704]) - io: support PRIORITY epoll events (#​5566]) - task: add `JoinSet::poll_join_next` (#​5721]) - net: add support for Redox OS (#​5790]) ##### Unstable - rt: add the ability to dump task backtraces (#​5608], #​5676], #​5708], #​5717]) - rt: instrument task poll times with a histogram (#​5685]) #​5766]: tokio-rs/tokio#5766 #​5653]: tokio-rs/tokio#5653 #​5686]: tokio-rs/tokio#5686 #​5712]: tokio-rs/tokio#5712 #​5693]: tokio-rs/tokio#5693 #​5772]: tokio-rs/tokio#5772 #​5710]: tokio-rs/tokio#5710 #​5803]: tokio-rs/tokio#5803 #​5705]: tokio-rs/tokio#5705 #​5720]: tokio-rs/tokio#5720 #​5659]: tokio-rs/tokio#5659 #​5628]: tokio-rs/tokio#5628 #​5666]: tokio-rs/tokio#5666 #​5672]: tokio-rs/tokio#5672 #​5690]: tokio-rs/tokio#5690 #​5704]: tokio-rs/tokio#5704 #​5566]: tokio-rs/tokio#5566 #​5721]: tokio-rs/tokio#5721 #​5790]: tokio-rs/tokio#5790 #​5608]: tokio-rs/tokio#5608 #​5676]: tokio-rs/tokio#5676 #​5708]: tokio-rs/tokio#5708 #​5717]: tokio-rs/tokio#5717 #​5685]: tokio-rs/tokio#5685 </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi4wLjAiLCJ1cGRhdGVkSW5WZXIiOiIzNi4wLjAiLCJ0YXJnZXRCcmFuY2giOiJkZXZlbG9wIn0=--> Co-authored-by: cabr2-bot <cabr2.help@gmail.com> Reviewed-on: https://codeberg.org/Calciumdibromid/CaBr2/pulls/1958 Reviewed-by: crapStone <crapstone01@gmail.com> Co-authored-by: Calciumdibromid Bot <cabr2_bot@noreply.codeberg.org> Co-committed-by: Calciumdibromid Bot <cabr2_bot@noreply.codeberg.org>
Motivation
Closes #4885
It was impossible in tokio to await
POLLPRI
events. These exceptional conditions are raised under certain circumstances on unix systems (e.g. when a new device is mounted, or when a UDP socket receives messages in its error queue).In version 8.6.0,
mio
addsInterest::PRIORITY
, (for the linux and android operating systems).Solution
mio
dependency to version8.6.0
Interest::PRIORITY
priority
andpriority_mut
functions toAsyncFd
Next steps
AsyncFd
already.mio
is trusted)mio
). Everything looks fine, but I may be missing something.