Support blocking for epoll#3804
Conversation
This should be EDIT: Ah, you don't. And it is indeed impossible, this approach is a dead end. Just using an owned |
|
☔ The latest upstream changes (presumably #3712) made this pull request unmergeable. Please resolve the merge conflicts. |
This works, thanks! |
|
☔ The latest upstream changes (presumably #3809) made this pull request unmergeable. Please resolve the merge conflicts. |
|
I wonder if it would make sense to implement #3665 first, as that's a much easier case of blocking? That might be a good way to learn how Miri deals with blocking. |
|
That's what I said, too, in our last meeting, and we realized it is not easier, as you need to refactor all read/write methods instead of just focussing on this one |
|
(If those are done first, I'd like to have a PR that passes |
Oh wait, so that does not have to happen for this one? Ah right, the blocking is in epoll_wait, not in read/write... makes sense. |
oli-obk
left a comment
There was a problem hiding this comment.
Please bless and fix the tokio sleep test
| // Collect all thread id of blocked threads that received notification. | ||
| let thread_id = epoll_event_interest.thread_id; | ||
| if this.has_blocked_on_epoll(thread_id) { | ||
| waiters.push(thread_id); |
There was a problem hiding this comment.
could also just wake here and record in a hashset whether the thread id was already woken
There was a problem hiding this comment.
For the new change in 9cb087d, I was trying to avoid using this.unblock_thread inside
if let Some(epoll_interests) = this.machine.epoll_interests.get_epoll_interest(id) { }because it will trigger this error:
error[E0502]: cannot borrow `*this` as mutable because it is also borrowed as immutable
--> src/shims/unix/linux/epoll.rs:594:29
|
568 | if let Some(epoll_interests) = this.machine.epoll_interests.get_epoll_interest(id) {
| ---------------------------- immutable borrow occurs here
...
573 | for weak_epoll_interest in epoll_interests {
| --------------- immutable borrow later used here
...
594 | this.unblock_thread(thread_id, BlockReason::Epoll)?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs hereSo instead I just store the ThreadIds that I want to unblock into a Vec then unblock them altogether outside of the block.
|
This is how it currently works: struct Epoll {
/// A map of EpollEventInterests registered under this epoll instance.
/// Each entry is differentiated using FdId and file descriptor value.
interest_list: RefCell<BTreeMap<(FdId, i32), Rc<RefCell<EpollEventInterest>>>>,
/// A map of EpollEventInstance that will be returned when `epoll_wait` is called.
/// Similar to interest_list, the entry is also differentiated using FdId
/// and file descriptor value.
// This is an Rc because EpollInterest need to hold a reference to update
// it.
ready_list: Rc<RefCell<BTreeMap<(FdId, i32), EpollEventInstance>>>,
/// A list of thread ids blocked on this epoll instance.
thread_id: RefCell<Vec<ThreadId>>, // < this is newly added
}Later in |
|
@rustbot ready |
|
The PR's main message is a bit outdated |
|
Do we want another test for triggering a notification after the |
|
There should be such a test in your libc-epoll-blocking test file.
But doesn't `test_epoll_block_without_notification` do that?
|
No, that test only epoll_wait, then timeout without notification. A notification need to be sent after timeout to trigger the bug. Also there is an error on the comment for that test, sorry for the confusion. |
|
Okay, just make sure the test has a comment explaining the exact scenario. :) |
|
@bors r+ |
|
☀️ Test successful - checks-actions |
Add tokio io test After #3804 landed, these tests passed.
This PR enabled epoll to have blocking operation.
The changes introduced by this PR are:
epoll_waittoblocking_epoll_callbackthread_idsinEpollfor blocked thread idsBlockReason::Epoll