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