Skip to content

Commit 13e2bfe

Browse files
committed
Sync the libc version of PollFd with the linux_raw version.
Port the `set_fd` and `AsFd` implementations from the linux_raw `PollFd` to the libc `PollFd`.
1 parent 12e9a88 commit 13e2bfe

File tree

3 files changed

+74
-2
lines changed

3 files changed

+74
-2
lines changed

src/imp/libc/io/poll_fd.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::super::c;
22
use super::super::conv::borrowed_fd;
3-
use crate::fd::{AsFd, BorrowedFd};
3+
use crate::fd::{AsFd, AsRawFd, BorrowedFd};
44
use bitflags::bitflags;
55
use core::marker::PhantomData;
66

@@ -61,6 +61,12 @@ impl<'fd> PollFd<'fd> {
6161
Self::from_borrowed_fd(fd.as_fd(), events)
6262
}
6363

64+
/// Sets the contained file descriptor to `fd`.
65+
#[inline]
66+
pub fn set_fd<Fd: AsFd>(&mut self, fd: &'fd Fd) {
67+
self.pollfd.fd = fd.as_fd().as_raw_fd();
68+
}
69+
6470
/// Constructs a new `PollFd` holding `fd` and `events`.
6571
///
6672
/// This is the same as `new`, but can be used to avoid borrowing the
@@ -78,11 +84,22 @@ impl<'fd> PollFd<'fd> {
7884
}
7985
}
8086

81-
/// Return the ready events.
87+
/// Returns the ready events.
8288
#[inline]
8389
pub fn revents(&self) -> PollFlags {
8490
// Use `unwrap()` here because in theory we know we know all the bits
8591
// the OS might set here, but OS's have added extensions in the past.
8692
PollFlags::from_bits(self.pollfd.revents).unwrap()
8793
}
8894
}
95+
96+
impl<'fd> AsFd for PollFd<'fd> {
97+
#[inline]
98+
fn as_fd(&self) -> BorrowedFd<'_> {
99+
// Safety:
100+
//
101+
// Our constructors and `set_fd` require `pollfd.fd` to be valid
102+
// for the `fd lifetime.
103+
unsafe { BorrowedFd::borrow_raw_fd(self.pollfd.fd) }
104+
}
105+
}

tests/io/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ mod isatty;
1919
#[cfg(not(windows))]
2020
mod mmap;
2121
#[cfg(not(windows))]
22+
mod poll;
23+
#[cfg(not(windows))]
2224
mod prot;
2325
#[cfg(not(windows))]
2426
#[cfg(not(target_os = "redox"))] // redox doesn't have cwd/openat

tests/io/poll.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use rustix::fd::{AsFd, AsRawFd, FromRawFd, IntoRawFd, OwnedFd};
2+
use rustix::io::{pipe, poll, read, with_retrying, write, PollFd, PollFlags};
3+
4+
#[test]
5+
fn test_poll() {
6+
// Create a pipe.
7+
let (reader, writer) = pipe().unwrap();
8+
let mut poll_fds = [PollFd::new(&reader, PollFlags::IN)];
9+
assert_eq!(poll_fds[0].as_fd().as_raw_fd(), reader.as_fd().as_raw_fd());
10+
11+
// `poll` should say there's nothing ready to be read fron the pipe.
12+
let num = with_retrying(|| poll(&mut poll_fds, 0)).unwrap();
13+
assert_eq!(num, 0);
14+
assert!(poll_fds[0].revents().is_empty());
15+
assert_eq!(poll_fds[0].as_fd().as_raw_fd(), reader.as_fd().as_raw_fd());
16+
17+
// Write a byte to the pipe.
18+
assert_eq!(with_retrying(|| write(&writer, b"a")).unwrap(), 1);
19+
20+
// `poll` should now say there's data to be read.
21+
let num = with_retrying(|| poll(&mut poll_fds, -1)).unwrap();
22+
assert_eq!(num, 1);
23+
assert_eq!(poll_fds[0].revents(), PollFlags::IN);
24+
assert_eq!(poll_fds[0].as_fd().as_raw_fd(), reader.as_fd().as_raw_fd());
25+
26+
// Read the byte from the pipe.
27+
let mut buf = [b'\0'];
28+
assert_eq!(with_retrying(|| read(&reader, &mut buf)).unwrap(), 1);
29+
assert_eq!(buf[0], b'a');
30+
assert_eq!(poll_fds[0].as_fd().as_raw_fd(), reader.as_fd().as_raw_fd());
31+
32+
// Poll should now say there's no more data to be read.
33+
let num = with_retrying(|| poll(&mut poll_fds, 0)).unwrap();
34+
assert_eq!(num, 0);
35+
assert!(poll_fds[0].revents().is_empty());
36+
assert_eq!(poll_fds[0].as_fd().as_raw_fd(), reader.as_fd().as_raw_fd());
37+
}
38+
39+
#[test]
40+
fn test_poll_fd_set_fd() {
41+
// Make up some file descriptors so that we can test that set_fd works.
42+
let a = unsafe { OwnedFd::from_raw_fd(777) };
43+
let mut poll_fd = PollFd::new(&a, PollFlags::empty());
44+
assert_eq!(poll_fd.as_fd().as_raw_fd(), 777);
45+
46+
let b = unsafe { OwnedFd::from_raw_fd(888) };
47+
poll_fd.set_fd(&b);
48+
assert_eq!(poll_fd.as_fd().as_raw_fd(), 888);
49+
50+
// Don't attempt to close our made-up file descriptors.
51+
let _ = a.into_raw_fd();
52+
let _ = b.into_raw_fd();
53+
}

0 commit comments

Comments
 (0)