Skip to content

Commit 0f3ff9a

Browse files
authored
Backport fcntl_setpipe_size fixes to 0.38. (#1166)
Backport parts of #1164 and #1165 to 0.38, but without the change to the public return type, to preserve semver compatibility for 0.38.
1 parent 6b2c700 commit 0f3ff9a

File tree

5 files changed

+79
-11
lines changed

5 files changed

+79
-11
lines changed

src/backend/libc/pipe/syscalls.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,17 @@ pub(crate) fn tee(
112112

113113
#[cfg(linux_kernel)]
114114
#[inline]
115-
pub(crate) fn fcntl_getpipe_sz(fd: BorrowedFd<'_>) -> io::Result<usize> {
115+
pub(crate) fn fcntl_getpipe_size(fd: BorrowedFd<'_>) -> io::Result<usize> {
116116
unsafe { ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GETPIPE_SZ)).map(|size| size as usize) }
117117
}
118118

119119
#[cfg(linux_kernel)]
120120
#[inline]
121-
pub(crate) fn fcntl_setpipe_sz(fd: BorrowedFd<'_>, size: usize) -> io::Result<()> {
121+
pub(crate) fn fcntl_setpipe_size(fd: BorrowedFd<'_>, size: usize) -> io::Result<()> {
122122
let size: c::c_int = size.try_into().map_err(|_| io::Errno::PERM)?;
123123

124-
unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_SETPIPE_SZ, size)) }
124+
unsafe {
125+
let _ = ret_c_int(c::fcntl(borrowed_fd(fd), c::F_SETPIPE_SZ, size))?;
126+
}
127+
Ok(())
125128
}

src/backend/linux_raw/pipe/syscalls.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub(crate) fn tee(
9999
}
100100

101101
#[inline]
102-
pub(crate) fn fcntl_getpipe_sz(fd: BorrowedFd<'_>) -> io::Result<usize> {
102+
pub(crate) fn fcntl_getpipe_size(fd: BorrowedFd<'_>) -> io::Result<usize> {
103103
#[cfg(target_pointer_width = "32")]
104104
unsafe {
105105
ret_usize(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GETPIPE_SZ)))
@@ -111,25 +111,27 @@ pub(crate) fn fcntl_getpipe_sz(fd: BorrowedFd<'_>) -> io::Result<usize> {
111111
}
112112

113113
#[inline]
114-
pub(crate) fn fcntl_setpipe_sz(fd: BorrowedFd<'_>, size: usize) -> io::Result<()> {
114+
pub(crate) fn fcntl_setpipe_size(fd: BorrowedFd<'_>, size: usize) -> io::Result<()> {
115115
let size: c::c_int = size.try_into().map_err(|_| io::Errno::PERM)?;
116116

117117
#[cfg(target_pointer_width = "32")]
118118
unsafe {
119-
ret(syscall_readonly!(
119+
let _ = ret_usize(syscall_readonly!(
120120
__NR_fcntl64,
121121
fd,
122122
c_uint(F_SETPIPE_SZ),
123123
c_int(size)
124-
))
124+
))?;
125125
}
126126
#[cfg(target_pointer_width = "64")]
127127
unsafe {
128-
ret(syscall_readonly!(
128+
let _ = ret_usize(syscall_readonly!(
129129
__NR_fcntl,
130130
fd,
131131
c_uint(F_SETPIPE_SZ),
132132
c_int(size)
133-
))
133+
))?;
134134
}
135+
136+
Ok(())
135137
}

src/pipe.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,17 +204,21 @@ pub fn tee<FdIn: AsFd, FdOut: AsFd>(
204204
#[cfg(linux_kernel)]
205205
#[inline]
206206
pub fn fcntl_getpipe_size<Fd: AsFd>(fd: Fd) -> io::Result<usize> {
207-
backend::pipe::syscalls::fcntl_getpipe_sz(fd.as_fd())
207+
backend::pipe::syscalls::fcntl_getpipe_size(fd.as_fd())
208208
}
209209

210210
/// `fnctl(fd, F_SETPIPE_SZ)`—Set the buffer capacity of a pipe.
211211
///
212+
/// The OS may decide to use a larger size than `size`. To know the precise
213+
/// size, call [`fcntl_getpipe_size`] after setting the size. In future
214+
/// versions of rustix, this function will return the new size.
215+
///
212216
/// # References
213217
/// - [Linux]
214218
///
215219
/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
216220
#[cfg(linux_kernel)]
217221
#[inline]
218222
pub fn fcntl_setpipe_size<Fd: AsFd>(fd: Fd, size: usize) -> io::Result<()> {
219-
backend::pipe::syscalls::fcntl_setpipe_sz(fd.as_fd(), size)
223+
backend::pipe::syscalls::fcntl_setpipe_size(fd.as_fd(), size)
220224
}

tests/pipe/fcntl.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#[cfg(linux_kernel)]
2+
#[test]
3+
fn test_fcntl_getpipe_size() {
4+
use rustix::pipe::fcntl_getpipe_size;
5+
6+
let (reader, writer) = rustix::pipe::pipe().unwrap();
7+
8+
let reader_size = fcntl_getpipe_size(&reader).unwrap();
9+
let writer_size = fcntl_getpipe_size(&writer).unwrap();
10+
assert_eq!(reader_size, writer_size);
11+
}
12+
13+
#[cfg(linux_kernel)]
14+
#[test]
15+
fn test_fcntl_setpipe_size() {
16+
use rustix::pipe::{fcntl_getpipe_size, fcntl_setpipe_size};
17+
18+
let (reader, writer) = rustix::pipe::pipe().unwrap();
19+
20+
let new_size = 4096 * 2;
21+
fcntl_setpipe_size(&reader, new_size).unwrap();
22+
let writer_size = fcntl_getpipe_size(&writer).unwrap();
23+
assert_eq!(new_size, writer_size);
24+
25+
let new_size = 4096 * 16;
26+
fcntl_setpipe_size(&reader, new_size).unwrap();
27+
let writer_size = fcntl_getpipe_size(&writer).unwrap();
28+
assert_eq!(new_size, writer_size);
29+
}
30+
31+
/// Test that we can write up to the pipe buffer size without blocking.
32+
#[cfg(linux_kernel)]
33+
#[test]
34+
fn test_fcntl_pipe_sized_writes() {
35+
use rustix::io::{read, write};
36+
use rustix::pipe::{fcntl_getpipe_size, fcntl_setpipe_size};
37+
38+
let (reader, writer) = rustix::pipe::pipe().unwrap();
39+
40+
let size = fcntl_getpipe_size(&reader).unwrap();
41+
42+
let ones = vec![1; size];
43+
assert_eq!(write(&writer, &ones), Ok(size));
44+
let mut buf = vec![2; size];
45+
assert_eq!(read(&reader, &mut buf), Ok(size));
46+
assert_eq!(buf, ones);
47+
48+
let size = size * 2;
49+
fcntl_setpipe_size(&reader, size).unwrap();
50+
let get_size = fcntl_getpipe_size(&reader).unwrap();
51+
assert_eq!(size, get_size);
52+
53+
let ones = vec![1; size];
54+
assert_eq!(write(&writer, &ones), Ok(size));
55+
let mut buf = vec![2; size];
56+
assert_eq!(read(&reader, &mut buf), Ok(size));
57+
assert_eq!(buf, ones);
58+
}

tests/pipe/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
#![cfg(not(windows))]
55

66
mod basic;
7+
mod fcntl;
78
mod splice;
89
mod tee;

0 commit comments

Comments
 (0)