rlimit/
tools.rs

1use std::io;
2
3/// Returns the value of `kern.maxfilesperproc` by sysctl.
4/// # Errors
5/// Returns an error if any syscall failed.
6#[cfg(any(
7    any(target_os = "macos", target_os = "ios"),
8    target_os = "dragonfly",
9    target_os = "freebsd",
10))]
11fn get_kern_max_files_per_proc() -> io::Result<u64> {
12    use std::mem;
13    use std::ptr;
14
15    let mut mib = [libc::CTL_KERN, libc::KERN_MAXFILESPERPROC];
16    let mut max_files_per_proc: libc::c_int = 0;
17    let mut oldlen = mem::size_of::<libc::c_int>();
18    let ret = unsafe {
19        libc::sysctl(
20            mib.as_mut_ptr(),
21            2,
22            &mut max_files_per_proc as *mut libc::c_int as *mut libc::c_void,
23            &mut oldlen,
24            ptr::null_mut(),
25            0,
26        )
27    };
28
29    if ret < 0 {
30        return Err(io::Error::last_os_error());
31    }
32
33    debug_assert!(max_files_per_proc >= 0);
34    Ok(max_files_per_proc as u64)
35}
36
37/// Try to increase NOFILE limit and return the current soft limit.
38///
39/// `lim` is the expected limit which can be up to [`u64::MAX`].
40///
41/// This function does nothing and returns `Ok(lim)`
42/// if `RLIMIT_NOFILE` does not exist on current platform.
43///
44/// # Errors
45/// Returns an error if any syscall failed.
46pub fn increase_nofile_limit(lim: u64) -> io::Result<u64> {
47    #[cfg(unix)]
48    {
49        use crate::Resource;
50
51        if !Resource::NOFILE.is_supported() {
52            return Ok(lim);
53        }
54
55        let (soft, hard) = Resource::NOFILE.get()?;
56
57        if soft >= hard {
58            return Ok(hard);
59        }
60
61        if soft >= lim {
62            return Ok(soft);
63        }
64
65        let mut lim = lim;
66
67        lim = lim.min(hard);
68
69        #[cfg(any(
70            any(target_os = "macos", target_os = "ios"),
71            target_os = "dragonfly",
72            target_os = "freebsd",
73        ))]
74        {
75            lim = lim.min(get_kern_max_files_per_proc()?)
76        }
77
78        Resource::NOFILE.set(lim, hard)?;
79
80        Ok(lim)
81    }
82    #[cfg(windows)]
83    {
84        Ok(lim)
85    }
86}