]> git.lizzy.rs Git - rust.git/blobdiff - library/std/src/sys/unix/fd.rs
Query maximum vector count on Linux and macOS
[rust.git] / library / std / src / sys / unix / fd.rs
index 84c4d662161bca7fac8a938c71e5799618787e10..675528bd5267bae52a6af27dc03462e1d78cd48f 100644 (file)
@@ -26,6 +26,27 @@ pub struct FileDesc {
 #[cfg(not(target_os = "macos"))]
 const READ_LIMIT: usize = libc::ssize_t::MAX as usize;
 
+#[cfg(any(target_os = "linux", target_os = "macos"))]
+fn max_iov() -> c_int {
+    let ret = unsafe {
+        libc::sysconf(
+            #[cfg(target_os = "linux")]
+            libc::_SC_IOV_MAX,
+            #[cfg(target_os = "macos")]
+            libc::_SC_UIO_MAXIOV,
+        )
+    };
+
+    // 1024 is the default value on modern Linux systems
+    // and hopefully more useful than `c_int::MAX`.
+    if ret > 0 { ret as c_int } else { 1024 }
+}
+
+#[cfg(not(any(target_os = "linux", target_os = "macos")))]
+fn max_iov() -> c_int {
+    c_int::MAX
+}
+
 impl FileDesc {
     pub fn new(fd: c_int) -> FileDesc {
         FileDesc { fd }
@@ -54,7 +75,7 @@ pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
             libc::readv(
                 self.fd,
                 bufs.as_ptr() as *const libc::iovec,
-                cmp::min(bufs.len(), c_int::MAX as usize) as c_int,
+                cmp::min(bufs.len(), max_iov() as usize) as c_int,
             )
         })?;
         Ok(ret as usize)
@@ -111,7 +132,7 @@ pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
             libc::writev(
                 self.fd,
                 bufs.as_ptr() as *const libc::iovec,
-                cmp::min(bufs.len(), c_int::MAX as usize) as c_int,
+                cmp::min(bufs.len(), max_iov() as usize) as c_int,
             )
         })?;
         Ok(ret as usize)
@@ -256,3 +277,16 @@ fn drop(&mut self) {
         let _ = unsafe { libc::close(self.fd) };
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::{FileDesc, IoSlice};
+
+    #[test]
+    fn limit_vector_count() {
+        let stdout = FileDesc { fd: 1 };
+        let bufs = (0..1500).map(|_| IoSlice::new(&[])).collect::<Vec<_>>();
+
+        assert!(stdout.write_vectored(&bufs).is_ok());
+    }
+}