Skip to content

Commit ea88824

Browse files
asomersSteveLauC
andauthored
Relax lifetime requirements for PollFd::new (#2134)
* Relax lifetime requirements for PollFd::new Fixes #2118 * Take BorrowedFd as the argument for PollFd::new &AsFd didn't work because there are 'static types, like std::fs::File, which implement AsFd. The created BorrowedFd type within the PollFd::new method would have a very brief lifetime, but the PhantomData would capture the lifetime of the std::fs::File. Taking BorrowFd<'fd> argument makes the lifetime explicit. * fix legacy comment --------- Co-authored-by: Steve Lau <[email protected]>
1 parent 489621e commit ea88824

File tree

3 files changed

+31
-16
lines changed

3 files changed

+31
-16
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ This project adheres to [Semantic Versioning](https://semver.org/).
2525
- Changed `openat()` and `Dir::openat()`, now take optional `dirfd`s
2626
([#2139](https://github.com/nix-rust/nix/pull/2139))
2727

28+
- `PollFd::new` now takes a `BorrowedFd` argument, with relaxed lifetime
29+
requirements relative to the previous version.
30+
([#2134](https://github.com/nix-rust/nix/pull/2134))
31+
2832
- `FdSet::{insert, remove, contains}` now take `BorrowedFd` arguments, and have
2933
relaxed lifetime requirements relative to 0.27.1.
3034
([#2136](https://github.com/nix-rust/nix/pull/2136))

src/poll.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,35 @@ pub struct PollFd<'fd> {
2222
impl<'fd> PollFd<'fd> {
2323
/// Creates a new `PollFd` specifying the events of interest
2424
/// for a given file descriptor.
25-
//
26-
// Different from other I/O-safe interfaces, here, we have to take `AsFd`
27-
// by reference to prevent the case where the `fd` is closed but it is
28-
// still in use. For example:
25+
///
26+
/// # Examples
27+
/// ```no_run
28+
/// # use std::os::unix::io::{AsFd, AsRawFd, FromRawFd};
29+
/// # use nix::{
30+
/// # poll::{PollFd, PollFlags, poll},
31+
/// # unistd::{pipe, read}
32+
/// # };
33+
/// let (r, w) = pipe().unwrap();
34+
/// let pfd = PollFd::new(r.as_fd(), PollFlags::POLLIN);
35+
/// let mut fds = [pfd];
36+
/// poll(&mut fds, -1).unwrap();
37+
/// let mut buf = [0u8; 80];
38+
/// read(r.as_raw_fd(), &mut buf[..]);
39+
/// ```
40+
// Unlike I/O functions, constructors like this must take `BorrowedFd`
41+
// instead of AsFd or &AsFd. Otherwise, an `OwnedFd` argument would be
42+
// dropped at the end of the method, leaving the structure referencing a
43+
// closed file descriptor. For example:
2944
//
3045
// ```rust
31-
// let (reader, _) = pipe().unwrap();
32-
//
33-
// // If `PollFd::new()` takes `AsFd` by value, then `reader` will be consumed,
34-
// // but the file descriptor of `reader` will still be in use.
35-
// let pollfd = PollFd::new(reader, flag);
36-
//
46+
// let (r, _) = pipe().unwrap();
47+
// let pollfd = PollFd::new(r, flag); // Drops the OwnedFd
3748
// // Do something with `pollfd`, which uses the CLOSED fd.
3849
// ```
39-
pub fn new<Fd: AsFd>(fd: &'fd Fd, events: PollFlags) -> PollFd<'fd> {
50+
pub fn new(fd: BorrowedFd<'fd>, events: PollFlags) -> PollFd<'fd> {
4051
PollFd {
4152
pollfd: libc::pollfd {
42-
fd: fd.as_fd().as_raw_fd(),
53+
fd: fd.as_raw_fd(),
4354
events: events.bits(),
4455
revents: PollFlags::empty().bits(),
4556
},

test/test_poll.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use nix::{
33
poll::{poll, PollFd, PollFlags},
44
unistd::{pipe, write},
55
};
6-
use std::os::unix::io::BorrowedFd;
6+
use std::os::unix::io::{AsFd, BorrowedFd};
77

88
macro_rules! loop_while_eintr {
99
($poll_expr: expr) => {
@@ -20,7 +20,7 @@ macro_rules! loop_while_eintr {
2020
#[test]
2121
fn test_poll() {
2222
let (r, w) = pipe().unwrap();
23-
let mut fds = [PollFd::new(&r, PollFlags::POLLIN)];
23+
let mut fds = [PollFd::new(r.as_fd(), PollFlags::POLLIN)];
2424

2525
// Poll an idle pipe. Should timeout
2626
let nfds = loop_while_eintr!(poll(&mut fds, 100));
@@ -52,7 +52,7 @@ fn test_ppoll() {
5252

5353
let timeout = TimeSpec::milliseconds(1);
5454
let (r, w) = pipe().unwrap();
55-
let mut fds = [PollFd::new(&r, PollFlags::POLLIN)];
55+
let mut fds = [PollFd::new(r.as_fd(), PollFlags::POLLIN)];
5656

5757
// Poll an idle pipe. Should timeout
5858
let sigset = SigSet::empty();
@@ -71,7 +71,7 @@ fn test_ppoll() {
7171
#[test]
7272
fn test_pollfd_events() {
7373
let fd_zero = unsafe { BorrowedFd::borrow_raw(0) };
74-
let mut pfd = PollFd::new(&fd_zero, PollFlags::POLLIN);
74+
let mut pfd = PollFd::new(fd_zero.as_fd(), PollFlags::POLLIN);
7575
assert_eq!(pfd.events(), PollFlags::POLLIN);
7676
pfd.set_events(PollFlags::POLLOUT);
7777
assert_eq!(pfd.events(), PollFlags::POLLOUT);

0 commit comments

Comments
 (0)