Skip to content
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

Implement epoll shim #3712

Open
wants to merge 105 commits into
base: master
Choose a base branch
from
Open

Implement epoll shim #3712

wants to merge 105 commits into from

Conversation

tiif
Copy link
Contributor

@tiif tiif commented Jun 26, 2024

This PR implements non-blocking epoll for #3448 . The design for this PR is documented in https://hackmd.io/@tiif/SJatftrH0 .

@tiif
Copy link
Contributor Author

tiif commented Jun 26, 2024

@rustbot author

@rustbot rustbot added the S-waiting-on-author Status: Waiting for the PR author to address review comments label Jun 26, 2024
src/shims/unix/socket.rs Outdated Show resolved Hide resolved
src/shims/unix/socket.rs Outdated Show resolved Hide resolved
src/shims/unix/fd.rs Outdated Show resolved Hide resolved
src/shims/unix/fd.rs Outdated Show resolved Hide resolved
src/shims/unix/socket.rs Outdated Show resolved Hide resolved
src/shims/unix/socket.rs Outdated Show resolved Hide resolved
src/shims/unix/socket.rs Outdated Show resolved Hide resolved
src/shims/unix/socket.rs Outdated Show resolved Hide resolved
src/shims/unix/socket.rs Outdated Show resolved Hide resolved
Comment on lines +275 to +293
fn test_pointer() {
// Create an epoll instance.
let epfd = unsafe { libc::epoll_create1(0) };
assert_ne!(epfd, -1);

// Create a socketpair instance.
let mut fds = [-1, -1];
let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
assert_eq!(res, 0);

// Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET
// EPOLLET is negative number for i32 so casting is needed to do proper bitwise OR for u32.
let epollet = libc::EPOLLET as u32;
let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLRDHUP).unwrap() | epollet;
let data = MaybeUninit::<u64>::uninit().as_ptr();
let mut ev = libc::epoll_event { events: u32::try_from(flags).unwrap(), u64: data as u64 };
let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) };
assert_ne!(res, -1);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oli-obk Passing pointer to the epoll_event's field didn't throw any error under the current implementation. But we talked about rejecting pointers before here. Is the behaviour of this passing test expected?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cast causes an integer address to be produced. I think this means it can't be turned back into an actual pointer, but that's ok since we don't have a use case for it yet.

I think libc's epoll_event type is wrong and should be using a union for the data field. I guess for now anyone using this could be using https://doc.rust-lang.org/std/ptr/fn.with_exposed_provenance.html to get back a pointer on some platforms.

We'll need to evaluate whether tokio needs to store pointers here, but we can delay that to later imo

Copy link
Member

@RalfJung RalfJung Jul 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without knowing the context here -- if epoll has to store something that is "either an integer or a pointer", then Scalar would be the type to use, I think?

EDIT: Ah, postponing also works, as long as there is a comment in the code somewhere clarifying this.

@tiif tiif requested a review from oli-obk July 19, 2024 09:04
let epollet = libc::EPOLLET as u32;
let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLRDHUP).unwrap() | epollet;
let data = MaybeUninit::<u64>::uninit().as_ptr();
let mut ev = libc::epoll_event { events: u32::try_from(flags).unwrap(), u64: data as u64 };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let mut ev = libc::epoll_event { events: u32::try_from(flags).unwrap(), u64: data as u64 };
let mut ev = libc::epoll_event { events: u32::try_from(flags).unwrap(), u64: data.expose_provenance() as u64 };

Copy link
Contributor Author

@tiif tiif Jul 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expose_provenance is on nightly so error will be thrown when it is used. Is there any way to get around this?

Error:

error[E0658]: use of unstable library feature 'exposed_provenance'
   --> ./tests/pass-dep/libc/libc-epoll.rs:292:19
    |
292 |         u64: data.expose_provenance() as u64,
    |                   ^^^^^^^^^^^^^^^^^
    |
    = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information
    = help: add `#![feature(exposed_provenance)]` to the crate attributes to enable
    = note: this compiler was built on 2024-07-06; consider upgrading it if it is out of date

error: aborting due to 1 previous error

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can add the feature gate

src/shims/unix/socket.rs Outdated Show resolved Hide resolved
src/shims/unix/socket.rs Outdated Show resolved Hide resolved
@oli-obk oli-obk requested a review from RalfJung July 19, 2024 09:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Waiting for a review to complete
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants