nix/sys/
resource.rs

1//! Configure the process resource limits.
2use cfg_if::cfg_if;
3
4use crate::errno::Errno;
5use crate::Result;
6pub use libc::rlim_t;
7use std::mem;
8
9cfg_if! {
10    if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
11        use libc::{__rlimit_resource_t, rlimit};
12    } else if #[cfg(any(
13        target_os = "freebsd",
14        target_os = "openbsd",
15        target_os = "netbsd",
16        target_os = "macos",
17        target_os = "ios",
18        target_os = "android",
19        target_os = "dragonfly",
20        all(target_os = "linux", not(target_env = "gnu"))
21    ))]{
22        use libc::{c_int, rlimit};
23    }
24}
25
26libc_enum! {
27    /// Types of process resources.
28    ///
29    /// The Resource enum is platform dependent. Check different platform
30    /// manuals for more details. Some platform links have been provided for
31    /// easier reference (non-exhaustive).
32    ///
33    /// * [Linux](https://man7.org/linux/man-pages/man2/getrlimit.2.html)
34    /// * [FreeBSD](https://www.freebsd.org/cgi/man.cgi?query=setrlimit)
35    /// * [NetBSD](https://man.netbsd.org/setrlimit.2)
36
37    // linux-gnu uses u_int as resource enum, which is implemented in libc as
38    // well.
39    //
40    // https://gcc.gnu.org/legacy-ml/gcc/2015-08/msg00441.html
41    // https://github.com/rust-lang/libc/blob/master/src/unix/linux_like/linux/gnu/mod.rs
42    #[cfg_attr(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")), repr(u32))]
43    #[cfg_attr(any(
44            target_os = "freebsd",
45            target_os = "openbsd",
46            target_os = "netbsd",
47            target_os = "macos",
48            target_os = "ios",
49            target_os = "android",
50            target_os = "dragonfly",
51            all(target_os = "linux", not(any(target_env = "gnu", target_env = "uclibc")))
52        ), repr(i32))]
53    #[non_exhaustive]
54    pub enum Resource {
55        #[cfg(not(any(target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")))]
56        #[cfg_attr(docsrs, doc(cfg(all())))]
57        /// The maximum amount (in bytes) of virtual memory the process is
58        /// allowed to map.
59        RLIMIT_AS,
60        /// The largest size (in bytes) core(5) file that may be created.
61        RLIMIT_CORE,
62        /// The maximum amount of cpu time (in seconds) to be used by each
63        /// process.
64        RLIMIT_CPU,
65        /// The maximum size (in bytes) of the data segment for a process
66        RLIMIT_DATA,
67        /// The largest size (in bytes) file that may be created.
68        RLIMIT_FSIZE,
69        /// The maximum number of open files for this process.
70        RLIMIT_NOFILE,
71        /// The maximum size (in bytes) of the stack segment for a process.
72        RLIMIT_STACK,
73
74        #[cfg(target_os = "freebsd")]
75        #[cfg_attr(docsrs, doc(cfg(all())))]
76        /// The maximum number of kqueues this user id is allowed to create.
77        RLIMIT_KQUEUES,
78
79        #[cfg(any(target_os = "android", target_os = "linux"))]
80        #[cfg_attr(docsrs, doc(cfg(all())))]
81        /// A limit on the combined number of flock locks and fcntl leases that
82        /// this process may establish.
83        RLIMIT_LOCKS,
84
85        #[cfg(any(
86            target_os = "android",
87            target_os = "freebsd",
88            target_os = "openbsd",
89            target_os = "linux",
90            target_os = "netbsd"
91        ))]
92        #[cfg_attr(docsrs, doc(cfg(all())))]
93        /// The maximum size (in bytes) which a process may lock into memory
94        /// using the mlock(2) system call.
95        RLIMIT_MEMLOCK,
96
97        #[cfg(any(target_os = "android", target_os = "linux"))]
98        #[cfg_attr(docsrs, doc(cfg(all())))]
99        /// A limit on the number of bytes that can be allocated for POSIX
100        /// message queues  for  the  real  user  ID  of  the  calling process.
101        RLIMIT_MSGQUEUE,
102
103        #[cfg(any(target_os = "android", target_os = "linux"))]
104        #[cfg_attr(docsrs, doc(cfg(all())))]
105        /// A ceiling to which the process's nice value can be raised using
106        /// setpriority or nice.
107        RLIMIT_NICE,
108
109        #[cfg(any(
110            target_os = "android",
111            target_os = "freebsd",
112            target_os = "netbsd",
113            target_os = "openbsd",
114            target_os = "linux",
115        ))]
116        #[cfg_attr(docsrs, doc(cfg(all())))]
117        /// The maximum number of simultaneous processes for this user id.
118        RLIMIT_NPROC,
119
120        #[cfg(target_os = "freebsd")]
121        #[cfg_attr(docsrs, doc(cfg(all())))]
122        /// The maximum number of pseudo-terminals this user id is allowed to
123        /// create.
124        RLIMIT_NPTS,
125
126        #[cfg(any(target_os = "android",
127            target_os = "freebsd",
128            target_os = "netbsd",
129            target_os = "openbsd",
130            target_os = "linux",
131        ))]
132        #[cfg_attr(docsrs, doc(cfg(all())))]
133        /// When there is memory pressure and swap is available, prioritize
134        /// eviction of a process' resident pages beyond this amount (in bytes).
135        RLIMIT_RSS,
136
137        #[cfg(any(target_os = "android", target_os = "linux"))]
138        #[cfg_attr(docsrs, doc(cfg(all())))]
139        /// A ceiling on the real-time priority that may be set for this process
140        /// using sched_setscheduler and  sched_set‐ param.
141        RLIMIT_RTPRIO,
142
143        #[cfg(any(target_os = "linux"))]
144        #[cfg_attr(docsrs, doc(cfg(all())))]
145        /// A limit (in microseconds) on the amount of CPU time that a process
146        /// scheduled under a real-time scheduling policy may con‐ sume without
147        /// making a blocking system call.
148        RLIMIT_RTTIME,
149
150        #[cfg(any(target_os = "android", target_os = "linux"))]
151        #[cfg_attr(docsrs, doc(cfg(all())))]
152        /// A limit on the number of signals that may be queued for the real
153        /// user ID of the  calling  process.
154        RLIMIT_SIGPENDING,
155
156        #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
157        #[cfg_attr(docsrs, doc(cfg(all())))]
158        /// The maximum size (in bytes) of socket buffer usage for this user.
159        RLIMIT_SBSIZE,
160
161        #[cfg(target_os = "freebsd")]
162        #[cfg_attr(docsrs, doc(cfg(all())))]
163        /// The maximum size (in bytes) of the swap space that may be reserved
164        /// or used by all of this user id's processes.
165        RLIMIT_SWAP,
166
167        #[cfg(target_os = "freebsd")]
168        #[cfg_attr(docsrs, doc(cfg(all())))]
169        /// An alias for RLIMIT_AS.
170        RLIMIT_VMEM,
171    }
172}
173
174/// Get the current processes resource limits
175///
176/// The special value `RLIM_INFINITY` indicates that no limit will be
177/// enforced.
178///
179/// # Parameters
180///
181/// * `resource`: The [`Resource`] that we want to get the limits of.
182///
183/// # Examples
184///
185/// ```
186/// # use nix::sys::resource::{getrlimit, Resource};
187///
188/// let (soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap();
189/// println!("current soft_limit: {}", soft_limit);
190/// println!("current hard_limit: {}", hard_limit);
191/// ```
192///
193/// # References
194///
195/// [getrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215)
196///
197/// [`Resource`]: enum.Resource.html
198pub fn getrlimit(resource: Resource) -> Result<(rlim_t, rlim_t)> {
199    let mut old_rlim = mem::MaybeUninit::<rlimit>::uninit();
200
201    cfg_if! {
202        if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
203            let res = unsafe { libc::getrlimit(resource as __rlimit_resource_t, old_rlim.as_mut_ptr()) };
204        } else {
205            let res = unsafe { libc::getrlimit(resource as c_int, old_rlim.as_mut_ptr()) };
206        }
207    }
208
209    Errno::result(res).map(|_| {
210        let rlimit { rlim_cur, rlim_max } = unsafe { old_rlim.assume_init() };
211        (rlim_cur, rlim_max)
212    })
213}
214
215/// Set the current processes resource limits
216///
217/// # Parameters
218///
219/// * `resource`: The [`Resource`] that we want to set the limits of.
220/// * `soft_limit`: The value that the kernel enforces for the corresponding
221///   resource.
222/// * `hard_limit`: The ceiling for the soft limit. Must be lower or equal to
223///   the current hard limit for non-root users.
224///
225/// The special value `RLIM_INFINITY` indicates that no limit will be
226/// enforced.
227///
228/// # Examples
229///
230/// ```
231/// # use nix::sys::resource::{setrlimit, Resource};
232///
233/// let soft_limit = 512;
234/// let hard_limit = 1024;
235/// setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap();
236/// ```
237///
238/// # References
239///
240/// [setrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215)
241///
242/// [`Resource`]: enum.Resource.html
243///
244/// Note: `setrlimit` provides a safe wrapper to libc's `setrlimit`.
245pub fn setrlimit(
246    resource: Resource,
247    soft_limit: rlim_t,
248    hard_limit: rlim_t,
249) -> Result<()> {
250    let new_rlim = rlimit {
251        rlim_cur: soft_limit,
252        rlim_max: hard_limit,
253    };
254    cfg_if! {
255        if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
256            let res = unsafe { libc::setrlimit(resource as __rlimit_resource_t, &new_rlim as *const rlimit) };
257        }else{
258            let res = unsafe { libc::setrlimit(resource as c_int, &new_rlim as *const rlimit) };
259        }
260    }
261
262    Errno::result(res).map(drop)
263}