1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
//! Some tools for operating resource limits.

use std::io;

/// Returns the value of `kern.maxfilesperproc` by sysctl.
/// # Errors
/// Returns an error if any syscall failed.
// #begin-codegen KERN_MAXFILESPERPROC
// generated from rust-lang/libc 6568dacc81b2dd2edae571ab97bbca94bc662595
#[cfg(any(
    any(target_os = "macos", target_os = "ios"),
    target_os = "dragonfly",
    target_os = "freebsd",
))]
// #end-codegen KERN_MAXFILESPERPROC
pub fn get_kern_max_files_per_proc() -> io::Result<u64> {
    use std::mem;
    use std::ptr;

    let mut mib = [libc::CTL_KERN, libc::KERN_MAXFILESPERPROC];
    let mut max_files_per_proc: libc::c_int = 0;
    let mut oldlen = mem::size_of::<libc::c_int>();
    let ret = unsafe {
        libc::sysctl(
            mib.as_mut_ptr(),
            2,
            &mut max_files_per_proc as *mut libc::c_int as *mut libc::c_void,
            &mut oldlen,
            ptr::null_mut(),
            0,
        )
    };

    if ret < 0 {
        return Err(io::Error::last_os_error());
    }

    debug_assert!(max_files_per_proc >= 0);
    Ok(max_files_per_proc as u64)
}

/// Try to increase NOFILE limit and return the current soft limit.
///
/// `lim` is the expected limit which can be up to [`u64::MAX`].
///
/// This function does nothing if `RLIMIT_NOFILE` does not exist on current platform.
///
/// # Errors
/// Returns an error if any syscall failed.
pub fn increase_nofile_limit(lim: u64) -> io::Result<u64> {
    // #begin-codegen RLIMIT_NOFILE
    // generated from rust-lang/libc 6568dacc81b2dd2edae571ab97bbca94bc662595
    #[cfg(any(
        all(target_os = "linux", target_env = "gnu"),
        all(
            target_os = "linux",
            target_env = "musl",
            any(
                target_arch = "x86",
                target_arch = "mips",
                target_arch = "powerpc",
                target_arch = "hexagon",
                target_arch = "arm"
            )
        ),
        all(
            target_os = "linux",
            target_env = "musl",
            any(
                target_arch = "x86_64",
                target_arch = "aarch64",
                target_arch = "mips64",
                target_arch = "powerpc64"
            )
        ),
        all(
            target_os = "linux",
            target_env = "uclibc",
            any(target_arch = "mips", target_arch = "mips64")
        ),
        any(target_os = "freebsd", target_os = "dragonfly"),
        any(target_os = "macos", target_os = "ios"),
        any(target_os = "openbsd", target_os = "netbsd"),
        target_os = "android",
        target_os = "emscripten",
        target_os = "fuchsia",
        target_os = "haiku",
        target_os = "solarish",
    ))]
    // #end-codegen RLIMIT_NOFILE
    {
        use super::Resource;

        let (soft, hard) = Resource::NOFILE.get()?;

        if soft >= hard {
            return Ok(hard);
        }

        if soft >= lim {
            return Ok(soft);
        }

        let mut lim = lim;

        lim = lim.min(hard);

        // #begin-codegen KERN_MAXFILESPERPROC
        // generated from rust-lang/libc 6568dacc81b2dd2edae571ab97bbca94bc662595
        #[cfg(any(
            any(target_os = "macos", target_os = "ios"),
            target_os = "dragonfly",
            target_os = "freebsd",
        ))]
        // #end-codegen KERN_MAXFILESPERPROC
        {
            lim = lim.min(get_kern_max_files_per_proc()?)
        }

        Resource::NOFILE.set(lim, hard)?;

        Ok(lim)
    }

    // #begin-codegen not RLIMIT_NOFILE
    // generated from rust-lang/libc 6568dacc81b2dd2edae571ab97bbca94bc662595
    #[cfg(not(any(
        all(target_os = "linux", target_env = "gnu"),
        all(
            target_os = "linux",
            target_env = "musl",
            any(
                target_arch = "x86",
                target_arch = "mips",
                target_arch = "powerpc",
                target_arch = "hexagon",
                target_arch = "arm"
            )
        ),
        all(
            target_os = "linux",
            target_env = "musl",
            any(
                target_arch = "x86_64",
                target_arch = "aarch64",
                target_arch = "mips64",
                target_arch = "powerpc64"
            )
        ),
        all(
            target_os = "linux",
            target_env = "uclibc",
            any(target_arch = "mips", target_arch = "mips64")
        ),
        any(target_os = "freebsd", target_os = "dragonfly"),
        any(target_os = "macos", target_os = "ios"),
        any(target_os = "openbsd", target_os = "netbsd"),
        target_os = "android",
        target_os = "emscripten",
        target_os = "fuchsia",
        target_os = "haiku",
        target_os = "solarish",
    )))]
    // #end-codegen not RLIMIT_NOFILE
    {
        Ok(lim)
    }
}