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", target_env = "gnu"))]{
11        use libc::{__rlimit_resource_t, rlimit, RLIM_INFINITY};
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, RLIM_INFINITY};
23    }
24}
25
26libc_enum! {
27    /// The Resource enum is platform dependent. Check different platform
28    /// manuals for more details. Some platform links has been provided for
29    /// earier reference (non-exhaustive).
30    ///
31    /// * [Linux](https://man7.org/linux/man-pages/man2/getrlimit.2.html)
32    /// * [FreeBSD](https://www.freebsd.org/cgi/man.cgi?query=setrlimit)
33
34    // linux-gnu uses u_int as resource enum, which is implemented in libc as
35    // well.
36    //
37    // https://gcc.gnu.org/legacy-ml/gcc/2015-08/msg00441.html
38    // https://github.com/rust-lang/libc/blob/master/src/unix/linux_like/linux/gnu/mod.rs
39    #[cfg_attr(all(target_os = "linux", target_env = "gnu"), repr(u32))]
40    #[cfg_attr(any(
41            target_os = "freebsd",
42            target_os = "openbsd",
43            target_os = "netbsd",
44            target_os = "macos",
45            target_os = "ios",
46            target_os = "android",
47            target_os = "dragonfly",
48            all(target_os = "linux", not(target_env = "gnu"))
49        ), repr(i32))]
50    #[non_exhaustive]
51    pub enum Resource {
52        #[cfg(not(any(
53                    target_os = "freebsd",
54                    target_os = "netbsd",
55                    target_os = "openbsd"
56        )))]
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        /// The maximum number of kqueues this user id is allowed to create.
76        RLIMIT_KQUEUES,
77
78        #[cfg(any(target_os = "android", target_os = "linux"))]
79        /// A limit on the combined number of flock locks and fcntl leases that
80        /// this process may establish.
81        RLIMIT_LOCKS,
82
83        #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "openbsd", target_os = "linux"))]
84        /// The maximum size (in bytes) which a process may lock into memory
85        /// using the mlock(2) system call.
86        RLIMIT_MEMLOCK,
87
88        #[cfg(any(target_os = "android", target_os = "linux"))]
89        /// A limit on the number of bytes that can be allocated for POSIX
90        /// message queues  for  the  real  user  ID  of  the  calling process.
91        RLIMIT_MSGQUEUE,
92
93        #[cfg(any(target_os = "android", target_os = "linux"))]
94        /// A ceiling to which the process's nice value can be raised using
95        /// setpriority or nice.
96        RLIMIT_NICE,
97
98        #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "openbsd", target_os = "linux"))]
99        /// The maximum number of simultaneous processes for this user id.
100        RLIMIT_NPROC,
101
102        #[cfg(target_os = "freebsd")]
103        /// The maximum number of pseudo-terminals this user id is allowed to
104        /// create.
105        RLIMIT_NPTS,
106
107        #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "openbsd", target_os = "linux"))]
108        /// When there is memory pressure and swap is available, prioritize
109        /// eviction of a process' resident pages beyond this amount (in bytes).
110        RLIMIT_RSS,
111
112        #[cfg(any(target_os = "android", target_os = "linux"))]
113        /// A ceiling on the real-time priority that may be set for this process
114        /// using sched_setscheduler and  sched_set‐ param.
115        RLIMIT_RTPRIO,
116
117        #[cfg(any(target_os = "linux"))]
118        /// A limit (in microseconds) on the amount of CPU time that a process
119        /// scheduled under a real-time scheduling policy may con‐ sume without
120        /// making a blocking system call.
121        RLIMIT_RTTIME,
122
123        #[cfg(any(target_os = "android", target_os = "linux"))]
124        /// A limit on the number of signals that may be queued for the real
125        /// user ID of the  calling  process.
126        RLIMIT_SIGPENDING,
127
128        #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
129        /// The maximum size (in bytes) of socket buffer usage for this user.
130        RLIMIT_SBSIZE,
131
132        #[cfg(target_os = "freebsd")]
133        /// The maximum size (in bytes) of the swap space that may be reserved
134        /// or used by all of this user id's processes.
135        RLIMIT_SWAP,
136
137        #[cfg(target_os = "freebsd")]
138        /// An alias for RLIMIT_AS.
139        RLIMIT_VMEM,
140    }
141}
142
143/// Get the current processes resource limits
144///
145/// A value of `None` indicates the value equals to `RLIM_INFINITY` which means
146/// there is no limit.
147///
148/// # Parameters
149///
150/// * `resource`: The [`Resource`] that we want to get the limits of.
151///
152/// # Examples
153///
154/// ```
155/// # use nix::sys::resource::{getrlimit, Resource};
156///
157/// let (soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap();
158/// println!("current soft_limit: {:?}", soft_limit);
159/// println!("current hard_limit: {:?}", hard_limit);
160/// ```
161///
162/// # References
163///
164/// [getrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215)
165///
166/// [`Resource`]: enum.Resource.html
167pub fn getrlimit(resource: Resource) -> Result<(Option<rlim_t>, Option<rlim_t>)> {
168    let mut old_rlim = mem::MaybeUninit::<rlimit>::uninit();
169
170    cfg_if! {
171        if #[cfg(all(target_os = "linux", target_env = "gnu"))]{
172            let res = unsafe { libc::getrlimit(resource as __rlimit_resource_t, old_rlim.as_mut_ptr()) };
173        }else{
174            let res = unsafe { libc::getrlimit(resource as c_int, old_rlim.as_mut_ptr()) };
175        }
176    }
177
178    Errno::result(res).map(|_| {
179        let rlimit { rlim_cur, rlim_max } = unsafe { old_rlim.assume_init() };
180        (Some(rlim_cur), Some(rlim_max))
181    })
182}
183
184/// Set the current processes resource limits
185///
186/// # Parameters
187///
188/// * `resource`: The [`Resource`] that we want to set the limits of.
189/// * `soft_limit`: The value that the kernel enforces for the corresponding
190///   resource. Note: `None` input will be replaced by constant `RLIM_INFINITY`.
191/// * `hard_limit`: The ceiling for the soft limit. Must be lower or equal to
192///   the current hard limit for non-root users. Note: `None` input will be
193///   replaced by constant `RLIM_INFINITY`.
194///
195/// > Note: for some os (linux_gnu), setting hard_limit to `RLIM_INFINITY` can
196/// > results `EPERM` Error. So you will need to set the number explicitly.
197///
198/// # Examples
199///
200/// ```
201/// # use nix::sys::resource::{setrlimit, Resource};
202///
203/// let soft_limit = Some(512);
204/// let hard_limit = Some(1024);
205/// setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap();
206/// ```
207///
208/// # References
209///
210/// [setrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215)
211///
212/// [`Resource`]: enum.Resource.html
213///
214/// Note: `setrlimit` provides a safe wrapper to libc's `setrlimit`.
215pub fn setrlimit(
216    resource: Resource,
217    soft_limit: Option<rlim_t>,
218    hard_limit: Option<rlim_t>,
219) -> Result<()> {
220    let new_rlim = rlimit {
221        rlim_cur: soft_limit.unwrap_or(RLIM_INFINITY),
222        rlim_max: hard_limit.unwrap_or(RLIM_INFINITY),
223    };
224    cfg_if! {
225        if #[cfg(all(target_os = "linux", target_env = "gnu"))]{
226            let res = unsafe { libc::setrlimit(resource as __rlimit_resource_t, &new_rlim as *const rlimit) };
227        }else{
228            let res = unsafe { libc::setrlimit(resource as c_int, &new_rlim as *const rlimit) };
229        }
230    }
231
232    Errno::result(res).map(drop)
233}