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
//! rlimit - Resource limits.
//!
//! ## Set resource limit
//! ```no_run
//! # #[cfg(unix)]
//! # {
//! use rlimit::{setrlimit, Resource};
//!
//! const DEFAULT_SOFT_LIMIT: u64 = 4 * 1024 * 1024;
//! const DEFAULT_HARD_LIMIT: u64 = 8 * 1024 * 1024;
//! assert!(Resource::FSIZE.set(DEFAULT_SOFT_LIMIT, DEFAULT_HARD_LIMIT).is_ok());
//!
//! let soft = 16384;
//! let hard = soft * 2;
//! assert!(setrlimit(Resource::NOFILE, soft, hard).is_ok());
//! # }
//! ```
//!
//! ## Get resource limit
//! ```no_run
//! # #[cfg(unix)]
//! # {
//! use rlimit::{getrlimit, Resource};
//!
//! assert!(Resource::NOFILE.get().is_ok());
//! assert_eq!(getrlimit(Resource::CPU).unwrap(), (rlimit::INFINITY, rlimit::INFINITY));
//! # }
//! ```
//!
//! ## Windows
//!
//! Windows does not have Unix-like resource limits.
//! It only supports changing the number of simultaneously open files currently permitted at the stdio level.
//!
//! See the official documentation of
//! [`_getmaxstdio`](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/getmaxstdio?view=msvc-170)
//! and
//! [`_setmaxstdio`](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setmaxstdio?view=msvc-170).
//!
//! ```no_run
//! # #[cfg(windows)]
//! # {
//! println!("{}", rlimit::getmaxstdio()); // 512
//! rlimit::setmaxstdio(2048).unwrap();
//! println!("{}", rlimit::getmaxstdio()); // 2048
//! # }
//! ```
//!
//! ## Increase NOFILE limit
//! See the example [nofile](https://github.com/Nugine/rlimit/blob/main/examples/nofile.rs).
//!
//! You can also use the tool function [`rlimit::increase_nofile_limit`][`crate::increase_nofile_limit`]
//!
//! ```no_run
//! rlimit::increase_nofile_limit(10240).unwrap();
//! rlimit::increase_nofile_limit(u64::MAX).unwrap();
//! ```
//!
//! # Troubleshoot
//!
//! ## Failed to increase NOFILE to hard limit on macOS
//! On macOS, getrlimit by default reports that the hard limit is
//! unlimited, but there is usually a stricter hard limit discoverable
//! via sysctl (`kern.maxfilesperproc`). Failing to discover this secret stricter hard limit will
//! cause the call to setrlimit to fail.
//!
//! [`rlimit::increase_nofile_limit`][`crate::increase_nofile_limit`]
//! respects `kern.maxfilesperproc`.
//!

#![cfg_attr(docsrs, feature(doc_cfg))]
#![deny(
    missing_docs,
    missing_debug_implementations,
    clippy::all,
    clippy::pedantic,
    clippy::cargo
)]
#![allow(
    clippy::option_if_let_else,  // I don't like it. The match expression is more readable.
)]

#[allow(unused_macros)]
macro_rules! group {
    ($($item:item)*) => {
        $($item)*
    }
}

#[cfg(any(doc, windows))]
group! {
    mod windows;

    #[doc(inline)]
    pub use self::windows::*;
}

#[cfg(any(doc, unix))]
group! {
    mod bindings;

    mod unix;
    mod resource;

    #[doc(inline)]
    pub use self::unix::*;

    #[doc(inline)]
    pub use self::resource::Resource;
}

#[cfg(any(doc, target_os = "linux", target_os = "android"))]
group! {
    mod proc_limits;

    #[doc(inline)]
    pub use self::proc_limits::*;
}

mod tools;
#[doc(inline)]
pub use self::tools::*;

#[cfg(test)]
mod tests {
    #[test]
    fn build_cfg() {
        if cfg!(target_os = "linux") || cfg!(target_os = "android") {
            assert!(cfg!(rlimit__has_prlimit64));
            assert!(cfg!(not(rlimit__get_kern_max_files_per_proc)));
        }

        if cfg!(target_os = "macos") {
            assert!(cfg!(not(rlimit__has_prlimit64)));
            assert!(cfg!(rlimit__get_kern_max_files_per_proc));
        }
    }
}