diff --git a/CHANGELOG.md b/CHANGELOG.md index 51cf8a2f46..db2ad71831 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,10 @@ This project adheres to [Semantic Versioning](https://semver.org/). ([#2137](https://github.com/nix-rust/nix/pull/2137)) +- `PollFd::new` now takes a `BorrowedFd` argument, with relaxed lifetime + requirements relative to the previous version. + ([#2134](https://github.com/nix-rust/nix/pull/2134)) + - `FdSet::{insert, remove, contains}` now take `BorrowedFd` arguments, and have relaxed lifetime requirements relative to 0.27.1. ([#2136](https://github.com/nix-rust/nix/pull/2136)) diff --git a/src/poll.rs b/src/poll.rs index 7fc3dc85de..2a8b62d2ad 100644 --- a/src/poll.rs +++ b/src/poll.rs @@ -22,24 +22,35 @@ pub struct PollFd<'fd> { impl<'fd> PollFd<'fd> { /// Creates a new `PollFd` specifying the events of interest /// for a given file descriptor. - // - // Different from other I/O-safe interfaces, here, we have to take `AsFd` - // by reference to prevent the case where the `fd` is closed but it is - // still in use. For example: + /// + /// # Examples + /// ```no_run + /// # use std::os::unix::io::{AsFd, AsRawFd, FromRawFd}; + /// # use nix::{ + /// # poll::{PollFd, PollFlags, poll}, + /// # unistd::{pipe, read} + /// # }; + /// let (r, w) = pipe().unwrap(); + /// let pfd = PollFd::new(r.as_fd(), PollFlags::POLLIN); + /// let mut fds = [pfd]; + /// poll(&mut fds, -1).unwrap(); + /// let mut buf = [0u8; 80]; + /// read(r.as_raw_fd(), &mut buf[..]); + /// ``` + // Unlike I/O functions, constructors like this must take `BorrowedFd` + // instead of AsFd or &AsFd. Otherwise, an `OwnedFd` argument would be + // dropped at the end of the method, leaving the structure referencing a + // closed file descriptor. For example: // // ```rust - // let (reader, _) = pipe().unwrap(); - // - // // If `PollFd::new()` takes `AsFd` by value, then `reader` will be consumed, - // // but the file descriptor of `reader` will still be in use. - // let pollfd = PollFd::new(reader, flag); - // + // let (r, _) = pipe().unwrap(); + // let pollfd = PollFd::new(r, flag); // Drops the OwnedFd // // Do something with `pollfd`, which uses the CLOSED fd. // ``` - pub fn new(fd: &'fd Fd, events: PollFlags) -> PollFd<'fd> { + pub fn new(fd: BorrowedFd<'fd>, events: PollFlags) -> PollFd<'fd> { PollFd { pollfd: libc::pollfd { - fd: fd.as_fd().as_raw_fd(), + fd: fd.as_raw_fd(), events: events.bits(), revents: PollFlags::empty().bits(), }, diff --git a/test/test_poll.rs b/test/test_poll.rs index 30207c95ea..fb4291721d 100644 --- a/test/test_poll.rs +++ b/test/test_poll.rs @@ -3,7 +3,7 @@ use nix::{ poll::{poll, PollFd, PollFlags}, unistd::{pipe, write}, }; -use std::os::unix::io::BorrowedFd; +use std::os::unix::io::{AsFd, BorrowedFd}; macro_rules! loop_while_eintr { ($poll_expr: expr) => { @@ -20,7 +20,7 @@ macro_rules! loop_while_eintr { #[test] fn test_poll() { let (r, w) = pipe().unwrap(); - let mut fds = [PollFd::new(&r, PollFlags::POLLIN)]; + let mut fds = [PollFd::new(r.as_fd(), PollFlags::POLLIN)]; // Poll an idle pipe. Should timeout let nfds = loop_while_eintr!(poll(&mut fds, 100)); @@ -52,7 +52,7 @@ fn test_ppoll() { let timeout = TimeSpec::milliseconds(1); let (r, w) = pipe().unwrap(); - let mut fds = [PollFd::new(&r, PollFlags::POLLIN)]; + let mut fds = [PollFd::new(r.as_fd(), PollFlags::POLLIN)]; // Poll an idle pipe. Should timeout let sigset = SigSet::empty(); @@ -71,7 +71,7 @@ fn test_ppoll() { #[test] fn test_pollfd_events() { let fd_zero = unsafe { BorrowedFd::borrow_raw(0) }; - let mut pfd = PollFd::new(&fd_zero, PollFlags::POLLIN); + let mut pfd = PollFd::new(fd_zero.as_fd(), PollFlags::POLLIN); assert_eq!(pfd.events(), PollFlags::POLLIN); pfd.set_events(PollFlags::POLLOUT); assert_eq!(pfd.events(), PollFlags::POLLOUT);