Coverage Report

Created: 2026-03-28 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.28.0/src/sys/resource.rs
Line
Count
Source
1
//! Configure the process resource limits.
2
use cfg_if::cfg_if;
3
use libc::{c_int, c_long, rusage};
4
5
use crate::errno::Errno;
6
use crate::sys::time::TimeVal;
7
use crate::Result;
8
pub use libc::rlim_t;
9
pub use libc::RLIM_INFINITY;
10
use std::mem;
11
12
cfg_if! {
13
    if #[cfg(any(
14
        all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")),
15
        target_os = "hurd"
16
    ))]{
17
        use libc::{__rlimit_resource_t, rlimit};
18
    } else if #[cfg(any(
19
        bsd,
20
        target_os = "android",
21
        target_os = "aix",
22
        all(target_os = "linux", not(target_env = "gnu"))
23
    ))]{
24
        use libc::rlimit;
25
    }
26
}
27
28
libc_enum! {
29
    /// Types of process resources.
30
    ///
31
    /// The Resource enum is platform dependent. Check different platform
32
    /// manuals for more details. Some platform links have been provided for
33
    /// easier reference (non-exhaustive).
34
    ///
35
    /// * [Linux](https://man7.org/linux/man-pages/man2/getrlimit.2.html)
36
    /// * [FreeBSD](https://www.freebsd.org/cgi/man.cgi?query=setrlimit)
37
    /// * [NetBSD](https://man.netbsd.org/setrlimit.2)
38
39
    // linux-gnu uses u_int as resource enum, which is implemented in libc as
40
    // well.
41
    //
42
    // https://gcc.gnu.org/legacy-ml/gcc/2015-08/msg00441.html
43
    // https://github.com/rust-lang/libc/blob/master/src/unix/linux_like/linux/gnu/mod.rs
44
    #[cfg_attr(any(
45
            all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")),
46
            target_os = "hurd"
47
        ), repr(u32))]
48
    #[cfg_attr(any(
49
            bsd,
50
            target_os = "android",
51
            target_os = "aix",
52
            all(target_os = "linux", not(any(target_env = "gnu", target_env = "uclibc")))
53
        ), repr(i32))]
54
    #[non_exhaustive]
55
    pub enum Resource {
56
        #[cfg(not(any(target_os = "freebsd", netbsdlike)))]
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(linux_android)]
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(linux_android, target_os = "freebsd", netbsdlike))]
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(linux_android)]
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(linux_android)]
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(
99
            linux_android,
100
            target_os = "freebsd",
101
            netbsdlike,
102
            target_os = "aix",
103
        ))]
104
        /// The maximum number of simultaneous processes for this user id.
105
        RLIMIT_NPROC,
106
107
        #[cfg(target_os = "freebsd")]
108
        /// The maximum number of pseudo-terminals this user id is allowed to
109
        /// create.
110
        RLIMIT_NPTS,
111
112
        #[cfg(any(linux_android,
113
            target_os = "freebsd",
114
            netbsdlike,
115
            target_os = "aix",
116
        ))]
117
        /// When there is memory pressure and swap is available, prioritize
118
        /// eviction of a process' resident pages beyond this amount (in bytes).
119
        RLIMIT_RSS,
120
121
        #[cfg(linux_android)]
122
        /// A ceiling on the real-time priority that may be set for this process
123
        /// using sched_setscheduler and  sched_set‐ param.
124
        RLIMIT_RTPRIO,
125
126
        #[cfg(any(target_os = "linux"))]
127
        /// A limit (in microseconds) on the amount of CPU time that a process
128
        /// scheduled under a real-time scheduling policy may con‐ sume without
129
        /// making a blocking system call.
130
        RLIMIT_RTTIME,
131
132
        #[cfg(linux_android)]
133
        /// A limit on the number of signals that may be queued for the real
134
        /// user ID of the  calling  process.
135
        RLIMIT_SIGPENDING,
136
137
        #[cfg(freebsdlike)]
138
        /// The maximum size (in bytes) of socket buffer usage for this user.
139
        RLIMIT_SBSIZE,
140
141
        #[cfg(target_os = "freebsd")]
142
        /// The maximum size (in bytes) of the swap space that may be reserved
143
        /// or used by all of this user id's processes.
144
        RLIMIT_SWAP,
145
146
        #[cfg(target_os = "freebsd")]
147
        /// An alias for RLIMIT_AS.
148
        RLIMIT_VMEM,
149
    }
150
}
151
152
/// Get the current processes resource limits
153
///
154
/// The special value [`RLIM_INFINITY`] indicates that no limit will be
155
/// enforced.
156
///
157
/// # Parameters
158
///
159
/// * `resource`: The [`Resource`] that we want to get the limits of.
160
///
161
/// # Examples
162
///
163
/// ```
164
/// # use nix::sys::resource::{getrlimit, Resource};
165
///
166
/// let (soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap();
167
/// println!("current soft_limit: {}", soft_limit);
168
/// println!("current hard_limit: {}", hard_limit);
169
/// ```
170
///
171
/// # References
172
///
173
/// [getrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215)
174
///
175
/// [`Resource`]: enum.Resource.html
176
0
pub fn getrlimit(resource: Resource) -> Result<(rlim_t, rlim_t)> {
177
0
    let mut old_rlim = mem::MaybeUninit::<rlimit>::uninit();
178
179
    cfg_if! {
180
        if #[cfg(any(
181
            all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")),
182
            target_os = "hurd"
183
        ))] {
184
0
            let res = unsafe { libc::getrlimit(resource as __rlimit_resource_t, old_rlim.as_mut_ptr()) };
185
        } else {
186
            let res = unsafe { libc::getrlimit(resource as c_int, old_rlim.as_mut_ptr()) };
187
        }
188
    }
189
190
0
    Errno::result(res).map(|_| {
191
0
        let rlimit { rlim_cur, rlim_max } = unsafe { old_rlim.assume_init() };
192
0
        (rlim_cur, rlim_max)
193
0
    })
194
0
}
195
196
/// Set the current processes resource limits
197
///
198
/// # Parameters
199
///
200
/// * `resource`: The [`Resource`] that we want to set the limits of.
201
/// * `soft_limit`: The value that the kernel enforces for the corresponding
202
///   resource.
203
/// * `hard_limit`: The ceiling for the soft limit. Must be lower or equal to
204
///   the current hard limit for non-root users.
205
///
206
/// The special value [`RLIM_INFINITY`] indicates that no limit will be
207
/// enforced.
208
///
209
/// # Examples
210
///
211
/// ```
212
/// # use nix::sys::resource::{setrlimit, Resource};
213
///
214
/// let soft_limit = 512;
215
/// let hard_limit = 1024;
216
/// setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap();
217
/// ```
218
///
219
/// # References
220
///
221
/// [setrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215)
222
///
223
/// [`Resource`]: enum.Resource.html
224
///
225
/// Note: `setrlimit` provides a safe wrapper to libc's `setrlimit`.
226
0
pub fn setrlimit(
227
0
    resource: Resource,
228
0
    soft_limit: rlim_t,
229
0
    hard_limit: rlim_t,
230
0
) -> Result<()> {
231
0
    let new_rlim = rlimit {
232
0
        rlim_cur: soft_limit,
233
0
        rlim_max: hard_limit,
234
0
    };
235
    cfg_if! {
236
        if #[cfg(any(
237
            all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")),
238
            target_os = "hurd",
239
        ))]{
240
0
            let res = unsafe { libc::setrlimit(resource as __rlimit_resource_t, &new_rlim as *const rlimit) };
241
        }else{
242
            let res = unsafe { libc::setrlimit(resource as c_int, &new_rlim as *const rlimit) };
243
        }
244
    }
245
246
0
    Errno::result(res).map(drop)
247
0
}
248
249
libc_enum! {
250
    /// Whose resource usage should be returned by [`getrusage`].
251
    #[repr(i32)]
252
    #[non_exhaustive]
253
    pub enum UsageWho {
254
        /// Resource usage for the current process.
255
        RUSAGE_SELF,
256
257
        /// Resource usage for all the children that have terminated and been waited for.
258
        RUSAGE_CHILDREN,
259
260
        #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"))]
261
        /// Resource usage for the calling thread.
262
        RUSAGE_THREAD,
263
    }
264
}
265
266
/// Output of `getrusage` with information about resource usage. Some of the fields
267
/// may be unused in some platforms, and will be always zeroed out. See their manuals
268
/// for details.
269
#[repr(transparent)]
270
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
271
pub struct Usage(rusage);
272
273
impl AsRef<rusage> for Usage {
274
0
    fn as_ref(&self) -> &rusage {
275
0
        &self.0
276
0
    }
277
}
278
279
impl AsMut<rusage> for Usage {
280
0
    fn as_mut(&mut self) -> &mut rusage {
281
0
        &mut self.0
282
0
    }
283
}
284
285
impl Usage {
286
    /// Total amount of time spent executing in user mode.
287
0
    pub fn user_time(&self) -> TimeVal {
288
0
        TimeVal::from(self.0.ru_utime)
289
0
    }
290
291
    /// Total amount of time spent executing in kernel mode.
292
0
    pub fn system_time(&self) -> TimeVal {
293
0
        TimeVal::from(self.0.ru_stime)
294
0
    }
295
296
    /// The resident set size at its peak, in kilobytes.
297
0
    pub fn max_rss(&self) -> c_long {
298
0
        self.0.ru_maxrss
299
0
    }
300
301
    /// Integral value expressed in kilobytes times ticks of execution indicating
302
    /// the amount of text memory shared with other processes.
303
0
    pub fn shared_integral(&self) -> c_long {
304
0
        self.0.ru_ixrss
305
0
    }
306
307
    /// Integral value expressed in kilobytes times ticks of execution indicating
308
    /// the amount of unshared memory used by data.
309
0
    pub fn unshared_data_integral(&self) -> c_long {
310
0
        self.0.ru_idrss
311
0
    }
312
313
    /// Integral value expressed in kilobytes times ticks of execution indicating
314
    /// the amount of unshared memory used for stack space.
315
0
    pub fn unshared_stack_integral(&self) -> c_long {
316
0
        self.0.ru_isrss
317
0
    }
318
319
    /// Number of page faults that were served without resorting to I/O, with pages
320
    /// that have been allocated previously by the kernel.
321
0
    pub fn minor_page_faults(&self) -> c_long {
322
0
        self.0.ru_minflt
323
0
    }
324
325
    /// Number of page faults that were served through I/O (i.e. swap).
326
0
    pub fn major_page_faults(&self) -> c_long {
327
0
        self.0.ru_majflt
328
0
    }
329
330
    /// Number of times all of the memory was fully swapped out.
331
0
    pub fn full_swaps(&self) -> c_long {
332
0
        self.0.ru_nswap
333
0
    }
334
335
    /// Number of times a read was done from a block device.
336
0
    pub fn block_reads(&self) -> c_long {
337
0
        self.0.ru_inblock
338
0
    }
339
340
    /// Number of times a write was done to a block device.
341
0
    pub fn block_writes(&self) -> c_long {
342
0
        self.0.ru_oublock
343
0
    }
344
345
    /// Number of IPC messages sent.
346
0
    pub fn ipc_sends(&self) -> c_long {
347
0
        self.0.ru_msgsnd
348
0
    }
349
350
    /// Number of IPC messages received.
351
0
    pub fn ipc_receives(&self) -> c_long {
352
0
        self.0.ru_msgrcv
353
0
    }
354
355
    /// Number of signals received.
356
0
    pub fn signals(&self) -> c_long {
357
0
        self.0.ru_nsignals
358
0
    }
359
360
    /// Number of times a context switch was voluntarily invoked.
361
0
    pub fn voluntary_context_switches(&self) -> c_long {
362
0
        self.0.ru_nvcsw
363
0
    }
364
365
    /// Number of times a context switch was imposed by the kernel (usually due to
366
    /// time slice expiring or preemption by a higher priority process).
367
0
    pub fn involuntary_context_switches(&self) -> c_long {
368
0
        self.0.ru_nivcsw
369
0
    }
370
}
371
372
/// Get usage information for a process, its children or the current thread
373
///
374
/// Real time information can be obtained for either the current process or (in some
375
/// systems) thread, but information about children processes is only provided for
376
/// those that have terminated and been waited for (see [`super::wait::wait`]).
377
///
378
/// Some information may be missing depending on the platform, and the way information
379
/// is provided for children may also vary. Check the manuals for details.
380
///
381
/// # References
382
///
383
/// * [getrusage(2)](https://pubs.opengroup.org/onlinepubs/009696699/functions/getrusage.html)
384
/// * [Linux](https://man7.org/linux/man-pages/man2/getrusage.2.html)
385
/// * [FreeBSD](https://www.freebsd.org/cgi/man.cgi?query=getrusage)
386
/// * [NetBSD](https://man.netbsd.org/getrusage.2)
387
/// * [MacOS](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getrusage.2.html)
388
///
389
/// [`UsageWho`]: enum.UsageWho.html
390
///
391
/// Note: `getrusage` provides a safe wrapper to libc's [`libc::getrusage`].
392
0
pub fn getrusage(who: UsageWho) -> Result<Usage> {
393
    unsafe {
394
0
        let mut rusage = mem::MaybeUninit::<rusage>::uninit();
395
0
        let res = libc::getrusage(who as c_int, rusage.as_mut_ptr());
396
0
        Errno::result(res).map(|_| Usage(rusage.assume_init()))
397
    }
398
0
}