From 63c438fb408e5678f580016ea3f8361b458314fc Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Sun, 1 Apr 2018 19:06:34 +0200 Subject: [PATCH 01/11] Add getrlimit(2) and setrlimit(2) --- src/sys/mod.rs | 2 ++ src/sys/resource.rs | 69 +++++++++++++++++++++++++++++++++++++++++++ test/test.rs | 1 + test/test_resource.rs | 22 ++++++++++++++ 4 files changed, 94 insertions(+) create mode 100644 src/sys/resource.rs create mode 100644 test/test_resource.rs diff --git a/src/sys/mod.rs b/src/sys/mod.rs index 972a1b5ea3..b62cdb670a 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -39,6 +39,8 @@ pub mod quota; #[cfg(any(target_os = "linux"))] pub mod reboot; +pub mod resource; + pub mod select; // TODO: Add support for dragonfly, freebsd, and ios/macos. diff --git a/src/sys/resource.rs b/src/sys/resource.rs new file mode 100644 index 0000000000..83b0123f0c --- /dev/null +++ b/src/sys/resource.rs @@ -0,0 +1,69 @@ +use std::mem; + +use libc::{self, c_int}; +pub use libc::{rlimit, rlim_t, RLIM_INFINITY}; + +#[cfg(any(target_os = "linux", + target_os = "openbsd", + target_os = "netbsd", + target_os = "bitrig"))] +pub use libc::{RLIM_SAVED_CUR, RLIM_SAVED_MAX}; + +use {Errno, Result}; + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum Resource { + // POSIX + RLIMIT_CORE = libc::RLIMIT_CORE, + RLIMIT_CPU = libc::RLIMIT_CPU, + RLIMIT_DATA = libc::RLIMIT_DATA, + RLIMIT_FSIZE = libc::RLIMIT_FSIZE, + RLIMIT_NOFILE = libc::RLIMIT_NOFILE, + RLIMIT_STACK = libc::RLIMIT_STACK, + RLIMIT_AS = libc::RLIMIT_AS, + // BSDs and Linux + #[cfg(all(unix, not(target_os = "solaris")))] + RLIMIT_MEMLOCK = libc::RLIMIT_MEMLOCK, + #[cfg(all(unix, not(target_os = "solaris")))] + RLIMIT_NPROC = libc::RLIMIT_NPROC, + #[cfg(all(unix, not(target_os = "solaris")))] + RLIMIT_RSS = libc::RLIMIT_RSS, + // Linux-only + #[cfg(any(target_os = "linux", target_os = "android"))] + RLIMIT_LOCKS = libc::RLIMIT_LOCKS, + #[cfg(any(target_os = "linux", target_os = "android"))] + RLIMIT_MSGQUEUE = libc::RLIMIT_MSGQUEUE, + #[cfg(any(target_os = "linux", target_os = "android"))] + RLIMIT_NICE = libc::RLIMIT_NICE, + #[cfg(any(target_os = "linux", target_os = "android"))] + RLIMIT_RTPRIO = libc::RLIMIT_RTPRIO, + #[cfg(any(target_os = "linux", target_os = "android"))] + RLIMIT_RTTIME = libc::RLIMIT_RTTIME, + #[cfg(any(target_os = "linux", target_os = "android"))] + RLIMIT_SIGPENDING = libc::RLIMIT_SIGPENDING, +} + +#[inline] +fn rlim_to_option(rlim: rlim_t) -> Option { + match rlim { + RLIM_INFINITY => None, + rlim => Some(rlim), + } +} + +pub fn getrlimit(resource: Resource) -> Result<(Option, Option)> { + let mut rlim: rlimit = unsafe { mem::uninitialized() }; + let res = unsafe { libc::getrlimit(resource as c_int, &mut rlim as *mut _) }; + Errno::result(res)?; + Ok((rlim_to_option(rlim.rlim_cur), rlim_to_option(rlim.rlim_max))) +} + +pub fn setrlimit(resource: Resource, limit: (Option, Option)) -> Result<()> { + let mut rlim: rlimit = unsafe { mem::uninitialized() }; + rlim.rlim_cur = limit.0.unwrap_or(RLIM_INFINITY); + rlim.rlim_max = limit.1.unwrap_or(RLIM_INFINITY); + + let res = unsafe { libc::setrlimit(resource as c_int, &rlim as *const _) }; + Errno::result(res).map(drop) +} diff --git a/test/test.rs b/test/test.rs index 6668e06e27..1f8ff73c5b 100644 --- a/test/test.rs +++ b/test/test.rs @@ -20,6 +20,7 @@ mod test_fcntl; mod test_mq; mod test_net; mod test_nix_path; +mod test_resource; mod test_poll; mod test_pty; #[cfg(any(target_os = "linux", target_os = "android"))] diff --git a/test/test_resource.rs b/test/test_resource.rs new file mode 100644 index 0000000000..0aa3023069 --- /dev/null +++ b/test/test_resource.rs @@ -0,0 +1,22 @@ +use nix::sys::resource::{Resource, getrlimit, setrlimit}; + +#[test] +pub fn test_resource_limits() { + let mut limit = getrlimit(Resource::RLIMIT_STACK).unwrap(); + assert!(limit.0 != limit.1); + + let orig_limit = limit; + + limit.0 = limit.1; + setrlimit(Resource::RLIMIT_STACK, limit).unwrap(); + + let limit2 = getrlimit(Resource::RLIMIT_STACK).unwrap(); + assert_eq!(limit.0, limit2.0); + assert_eq!(limit.1, limit2.1); + + setrlimit(Resource::RLIMIT_STACK, orig_limit).unwrap(); + + let final_limit = getrlimit(Resource::RLIMIT_STACK).unwrap(); + assert_eq!(orig_limit.0, final_limit.0); + assert_eq!(orig_limit.1, final_limit.1); +} From aaf89e4d4b2a407c7ea31c67114523aeaa5d4aa5 Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Sun, 1 Apr 2018 21:46:12 +0200 Subject: [PATCH 02/11] Update API --- src/sys/resource.rs | 48 +++++++++++++++++-------------------------- test/test_resource.rs | 16 +++++++-------- 2 files changed, 26 insertions(+), 38 deletions(-) diff --git a/src/sys/resource.rs b/src/sys/resource.rs index 83b0123f0c..e57a876812 100644 --- a/src/sys/resource.rs +++ b/src/sys/resource.rs @@ -1,13 +1,7 @@ use std::mem; -use libc::{self, c_int}; -pub use libc::{rlimit, rlim_t, RLIM_INFINITY}; - -#[cfg(any(target_os = "linux", - target_os = "openbsd", - target_os = "netbsd", - target_os = "bitrig"))] -pub use libc::{RLIM_SAVED_CUR, RLIM_SAVED_MAX}; +use libc::{self, c_int, rlimit, RLIM_INFINITY}; +pub use libc::rlim_t; use {Errno, Result}; @@ -15,13 +9,14 @@ use {Errno, Result}; #[repr(i32)] pub enum Resource { // POSIX + RLIMIT_AS = libc::RLIMIT_AS, RLIMIT_CORE = libc::RLIMIT_CORE, RLIMIT_CPU = libc::RLIMIT_CPU, RLIMIT_DATA = libc::RLIMIT_DATA, RLIMIT_FSIZE = libc::RLIMIT_FSIZE, RLIMIT_NOFILE = libc::RLIMIT_NOFILE, RLIMIT_STACK = libc::RLIMIT_STACK, - RLIMIT_AS = libc::RLIMIT_AS, + // BSDs and Linux #[cfg(all(unix, not(target_os = "solaris")))] RLIMIT_MEMLOCK = libc::RLIMIT_MEMLOCK, @@ -29,40 +24,35 @@ pub enum Resource { RLIMIT_NPROC = libc::RLIMIT_NPROC, #[cfg(all(unix, not(target_os = "solaris")))] RLIMIT_RSS = libc::RLIMIT_RSS, - // Linux-only - #[cfg(any(target_os = "linux", target_os = "android"))] + + // Android and Linux only + #[cfg(any(target_os = "android", target_os = "linux"))] RLIMIT_LOCKS = libc::RLIMIT_LOCKS, - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "android", target_os = "linux"))] RLIMIT_MSGQUEUE = libc::RLIMIT_MSGQUEUE, - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "android", target_os = "linux"))] RLIMIT_NICE = libc::RLIMIT_NICE, - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "android", target_os = "linux"))] RLIMIT_RTPRIO = libc::RLIMIT_RTPRIO, - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "android", target_os = "linux"))] RLIMIT_RTTIME = libc::RLIMIT_RTTIME, - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "android", target_os = "linux"))] RLIMIT_SIGPENDING = libc::RLIMIT_SIGPENDING, } -#[inline] -fn rlim_to_option(rlim: rlim_t) -> Option { - match rlim { - RLIM_INFINITY => None, - rlim => Some(rlim), - } -} - pub fn getrlimit(resource: Resource) -> Result<(Option, Option)> { let mut rlim: rlimit = unsafe { mem::uninitialized() }; let res = unsafe { libc::getrlimit(resource as c_int, &mut rlim as *mut _) }; - Errno::result(res)?; - Ok((rlim_to_option(rlim.rlim_cur), rlim_to_option(rlim.rlim_max))) + Errno::result(res).map(|_| { + (if rlim.rlim_cur != RLIM_INFINITY { Some(rlim.rlim_cur) } else { None }, + if rlim.rlim_max != RLIM_INFINITY { Some(rlim.rlim_max) } else { None }) + }) } -pub fn setrlimit(resource: Resource, limit: (Option, Option)) -> Result<()> { +pub fn setrlimit(resource: Resource, soft_limit: Option, hard_limit: Option) -> Result<()> { let mut rlim: rlimit = unsafe { mem::uninitialized() }; - rlim.rlim_cur = limit.0.unwrap_or(RLIM_INFINITY); - rlim.rlim_max = limit.1.unwrap_or(RLIM_INFINITY); + rlim.rlim_cur = soft_limit.unwrap_or(RLIM_INFINITY); + rlim.rlim_max = hard_limit.unwrap_or(RLIM_INFINITY); let res = unsafe { libc::setrlimit(resource as c_int, &rlim as *const _) }; Errno::result(res).map(drop) diff --git a/test/test_resource.rs b/test/test_resource.rs index 0aa3023069..d1dc9048d1 100644 --- a/test/test_resource.rs +++ b/test/test_resource.rs @@ -2,19 +2,17 @@ use nix::sys::resource::{Resource, getrlimit, setrlimit}; #[test] pub fn test_resource_limits() { - let mut limit = getrlimit(Resource::RLIMIT_STACK).unwrap(); - assert!(limit.0 != limit.1); + let (mut soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_STACK).unwrap(); + let orig_limit = (soft_limit, hard_limit); - let orig_limit = limit; - - limit.0 = limit.1; - setrlimit(Resource::RLIMIT_STACK, limit).unwrap(); + soft_limit = hard_limit; + setrlimit(Resource::RLIMIT_STACK, soft_limit, hard_limit).unwrap(); let limit2 = getrlimit(Resource::RLIMIT_STACK).unwrap(); - assert_eq!(limit.0, limit2.0); - assert_eq!(limit.1, limit2.1); + assert_eq!(soft_limit, limit2.0); + assert_eq!(hard_limit, limit2.1); - setrlimit(Resource::RLIMIT_STACK, orig_limit).unwrap(); + setrlimit(Resource::RLIMIT_STACK, orig_limit.0, orig_limit.1).unwrap(); let final_limit = getrlimit(Resource::RLIMIT_STACK).unwrap(); assert_eq!(orig_limit.0, final_limit.0); From f69bedbb6d8d6d39c8376d1bf76759b6c0466d8f Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Sun, 1 Apr 2018 21:50:08 +0200 Subject: [PATCH 03/11] Use libc_enum --- src/sys/resource.rs | 67 +++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/src/sys/resource.rs b/src/sys/resource.rs index e57a876812..faece905ac 100644 --- a/src/sys/resource.rs +++ b/src/sys/resource.rs @@ -5,39 +5,40 @@ pub use libc::rlim_t; use {Errno, Result}; -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -#[repr(i32)] -pub enum Resource { - // POSIX - RLIMIT_AS = libc::RLIMIT_AS, - RLIMIT_CORE = libc::RLIMIT_CORE, - RLIMIT_CPU = libc::RLIMIT_CPU, - RLIMIT_DATA = libc::RLIMIT_DATA, - RLIMIT_FSIZE = libc::RLIMIT_FSIZE, - RLIMIT_NOFILE = libc::RLIMIT_NOFILE, - RLIMIT_STACK = libc::RLIMIT_STACK, - - // BSDs and Linux - #[cfg(all(unix, not(target_os = "solaris")))] - RLIMIT_MEMLOCK = libc::RLIMIT_MEMLOCK, - #[cfg(all(unix, not(target_os = "solaris")))] - RLIMIT_NPROC = libc::RLIMIT_NPROC, - #[cfg(all(unix, not(target_os = "solaris")))] - RLIMIT_RSS = libc::RLIMIT_RSS, - - // Android and Linux only - #[cfg(any(target_os = "android", target_os = "linux"))] - RLIMIT_LOCKS = libc::RLIMIT_LOCKS, - #[cfg(any(target_os = "android", target_os = "linux"))] - RLIMIT_MSGQUEUE = libc::RLIMIT_MSGQUEUE, - #[cfg(any(target_os = "android", target_os = "linux"))] - RLIMIT_NICE = libc::RLIMIT_NICE, - #[cfg(any(target_os = "android", target_os = "linux"))] - RLIMIT_RTPRIO = libc::RLIMIT_RTPRIO, - #[cfg(any(target_os = "android", target_os = "linux"))] - RLIMIT_RTTIME = libc::RLIMIT_RTTIME, - #[cfg(any(target_os = "android", target_os = "linux"))] - RLIMIT_SIGPENDING = libc::RLIMIT_SIGPENDING, +libc_enum!{ + #[repr(i32)] + pub enum Resource { + // POSIX + RLIMIT_AS, + RLIMIT_CORE, + RLIMIT_CPU, + RLIMIT_DATA, + RLIMIT_FSIZE, + RLIMIT_NOFILE, + RLIMIT_STACK, + + // BSDs and Linux + #[cfg(all(unix, not(target_os = "solaris")))] + RLIMIT_MEMLOCK, + #[cfg(all(unix, not(target_os = "solaris")))] + RLIMIT_NPROC, + #[cfg(all(unix, not(target_os = "solaris")))] + RLIMIT_RSS, + + // Android and Linux only + #[cfg(any(target_os = "android", target_os = "linux"))] + RLIMIT_LOCKS, + #[cfg(any(target_os = "android", target_os = "linux"))] + RLIMIT_MSGQUEUE, + #[cfg(any(target_os = "android", target_os = "linux"))] + RLIMIT_NICE, + #[cfg(any(target_os = "android", target_os = "linux"))] + RLIMIT_RTPRIO, + #[cfg(any(target_os = "android", target_os = "linux"))] + RLIMIT_RTTIME, + #[cfg(any(target_os = "android", target_os = "linux"))] + RLIMIT_SIGPENDING, + } } pub fn getrlimit(resource: Resource) -> Result<(Option, Option)> { From 2c4d80406e5ab374f94eefa2181f45ab9a7c17e3 Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Sun, 1 Apr 2018 22:00:35 +0200 Subject: [PATCH 04/11] Add freebsd specific rlimits --- src/sys/resource.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/sys/resource.rs b/src/sys/resource.rs index faece905ac..fec5827b69 100644 --- a/src/sys/resource.rs +++ b/src/sys/resource.rs @@ -38,6 +38,16 @@ libc_enum!{ RLIMIT_RTTIME, #[cfg(any(target_os = "android", target_os = "linux"))] RLIMIT_SIGPENDING, + + // Non-Linux + #[cfg(target_os = "freebsd")] + RLIMIT_KQUEUES, + #[cfg(target_os = "freebsd")] + RLIMIT_NPTS, + #[cfg(target_os = "freebsd")] + RLIMIT_SBSIZE, + #[cfg(target_os = "freebsd")] + RLIMIT_SWAP, } } From 13f75c139ef81f2e3071b677af69bd0bf85c57bc Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Sun, 1 Apr 2018 22:02:39 +0200 Subject: [PATCH 05/11] Use explicit target_os list --- src/sys/resource.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sys/resource.rs b/src/sys/resource.rs index fec5827b69..1e6d28e3af 100644 --- a/src/sys/resource.rs +++ b/src/sys/resource.rs @@ -18,11 +18,11 @@ libc_enum!{ RLIMIT_STACK, // BSDs and Linux - #[cfg(all(unix, not(target_os = "solaris")))] + #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux", target_os = "openbsd"))] RLIMIT_MEMLOCK, - #[cfg(all(unix, not(target_os = "solaris")))] + #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux", target_os = "openbsd"))] RLIMIT_NPROC, - #[cfg(all(unix, not(target_os = "solaris")))] + #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux", target_os = "openbsd"))] RLIMIT_RSS, // Android and Linux only From 7b537e3d6b450291f3d71dfd41878286db4ab7b9 Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Mon, 2 Apr 2018 00:55:38 +0200 Subject: [PATCH 06/11] Add docs --- src/sys/resource.rs | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/sys/resource.rs b/src/sys/resource.rs index 1e6d28e3af..005570d7e9 100644 --- a/src/sys/resource.rs +++ b/src/sys/resource.rs @@ -1,3 +1,4 @@ +//! Configure the process resource limits. use std::mem; use libc::{self, c_int, rlimit, RLIM_INFINITY}; @@ -39,18 +40,31 @@ libc_enum!{ #[cfg(any(target_os = "android", target_os = "linux"))] RLIMIT_SIGPENDING, - // Non-Linux + // Available on some BSD #[cfg(target_os = "freebsd")] RLIMIT_KQUEUES, #[cfg(target_os = "freebsd")] RLIMIT_NPTS, - #[cfg(target_os = "freebsd")] + #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] RLIMIT_SBSIZE, #[cfg(target_os = "freebsd")] RLIMIT_SWAP, } } +/// Get the current processes resource limits +/// +/// A value of `None` corresponds to `RLIM_INFINITY`, which means there's no limit. +/// +/// # Parameters +/// +/// * `resource`: The [`Resource`] that we want to get the limits of. +/// +/// # References +/// +/// [getrlimit(2)](https://linux.die.net/man/2/getrlimit) +/// +/// [`Resource`]: enum.Resource.html pub fn getrlimit(resource: Resource) -> Result<(Option, Option)> { let mut rlim: rlimit = unsafe { mem::uninitialized() }; let res = unsafe { libc::getrlimit(resource as c_int, &mut rlim as *mut _) }; @@ -60,6 +74,22 @@ pub fn getrlimit(resource: Resource) -> Result<(Option, Option)> }) } +/// Set the current processes resource limits +/// +/// A value of `None` corresponds to `RLIM_INFINITY`, which means there's no limit. +/// +/// # Parameters +/// +/// * `resource`: The [`Resource`] that we want to set the limits of. +/// * `soft_limit`: The value that the kenrel enforces for the corresponding resource. +/// * `hard_limit`: The ceiling for the soft limit. Must be lower or equal to the current hard limit +/// for non-root users. +/// +/// # References +/// +/// [setrlimit(2)](https://linux.die.net/man/2/setrlimit) +/// +/// [`Resource`]: enum.Resource.html pub fn setrlimit(resource: Resource, soft_limit: Option, hard_limit: Option) -> Result<()> { let mut rlim: rlimit = unsafe { mem::uninitialized() }; rlim.rlim_cur = soft_limit.unwrap_or(RLIM_INFINITY); From 8c18615f4613c4734af649b4622cd7eba0e16079 Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Mon, 2 Apr 2018 01:01:14 +0200 Subject: [PATCH 07/11] Increase test coverage --- test/test_resource.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/test/test_resource.rs b/test/test_resource.rs index d1dc9048d1..336ed05ca4 100644 --- a/test/test_resource.rs +++ b/test/test_resource.rs @@ -1,7 +1,22 @@ use nix::sys::resource::{Resource, getrlimit, setrlimit}; #[test] -pub fn test_resource_limits() { +pub fn test_resource_limits_nofile() { + let (soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap(); + + // make sure the soft limit and hard limit are not equal + let soft_limit = match soft_limit { + Some(nofile) => Some(nofile -1), + None => Some(1024), + }; + setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap(); + + let (new_soft_limit, new_hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap(); + assert!(new_soft_limit != new_hard_limit); +} + +#[test] +pub fn test_resource_limits_stack() { let (mut soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_STACK).unwrap(); let orig_limit = (soft_limit, hard_limit); From de89045cffef29a09753c67d3dbb036abd0808e2 Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Mon, 2 Apr 2018 01:09:55 +0200 Subject: [PATCH 08/11] Add examples --- src/sys/resource.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/sys/resource.rs b/src/sys/resource.rs index 005570d7e9..3e54ad2057 100644 --- a/src/sys/resource.rs +++ b/src/sys/resource.rs @@ -60,6 +60,18 @@ libc_enum!{ /// /// * `resource`: The [`Resource`] that we want to get the limits of. /// +/// # Examples +/// +/// ``` +/// use nix::sys::resource::{getrlimit, Resource}; +/// +/// fn main() { +/// let (soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap(); +/// println!("current soft_limit: {:?}", soft_limit); +/// println!("current hard_limit: {:?}", hard_limit); +/// } +/// ``` +/// /// # References /// /// [getrlimit(2)](https://linux.die.net/man/2/getrlimit) @@ -85,6 +97,18 @@ pub fn getrlimit(resource: Resource) -> Result<(Option, Option)> /// * `hard_limit`: The ceiling for the soft limit. Must be lower or equal to the current hard limit /// for non-root users. /// +/// # Examples +/// +/// ```no_run +/// use nix::sys::resource::{setrlimit, Resource}; +/// +/// fn main() { +/// let soft_limit = Some(1024); +/// let hard_limit = None; +/// setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap(); +/// } +/// ``` +/// /// # References /// /// [setrlimit(2)](https://linux.die.net/man/2/setrlimit) From 724260710e12120ca08cc88857d25b0023a2ac12 Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Mon, 2 Apr 2018 02:35:17 +0200 Subject: [PATCH 09/11] Update documentation and tests --- src/sys/resource.rs | 28 +++++++++++++--------------- test/test_resource.rs | 2 +- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/sys/resource.rs b/src/sys/resource.rs index 3e54ad2057..1b8f85f068 100644 --- a/src/sys/resource.rs +++ b/src/sys/resource.rs @@ -63,13 +63,12 @@ libc_enum!{ /// # Examples /// /// ``` -/// use nix::sys::resource::{getrlimit, Resource}; -/// -/// fn main() { -/// let (soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap(); -/// println!("current soft_limit: {:?}", soft_limit); -/// println!("current hard_limit: {:?}", hard_limit); -/// } +/// # use nix::sys::resource::{getrlimit, Resource}; +/// # fn main() { +/// let (soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap(); +/// println!("current soft_limit: {:?}", soft_limit); +/// println!("current hard_limit: {:?}", hard_limit); +/// # } /// ``` /// /// # References @@ -93,20 +92,19 @@ pub fn getrlimit(resource: Resource) -> Result<(Option, Option)> /// # Parameters /// /// * `resource`: The [`Resource`] that we want to set the limits of. -/// * `soft_limit`: The value that the kenrel enforces for the corresponding resource. +/// * `soft_limit`: The value that the kernel enforces for the corresponding resource. /// * `hard_limit`: The ceiling for the soft limit. Must be lower or equal to the current hard limit /// for non-root users. /// /// # Examples /// /// ```no_run -/// use nix::sys::resource::{setrlimit, Resource}; -/// -/// fn main() { -/// let soft_limit = Some(1024); -/// let hard_limit = None; -/// setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap(); -/// } +/// # use nix::sys::resource::{setrlimit, Resource}; +/// # fn main() { +/// let soft_limit = Some(1024); +/// let hard_limit = None; +/// setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap(); +/// # } /// ``` /// /// # References diff --git a/test/test_resource.rs b/test/test_resource.rs index 336ed05ca4..7ca6d3940c 100644 --- a/test/test_resource.rs +++ b/test/test_resource.rs @@ -12,7 +12,7 @@ pub fn test_resource_limits_nofile() { setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap(); let (new_soft_limit, new_hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap(); - assert!(new_soft_limit != new_hard_limit); + assert_eq!(new_soft_limit, soft_limit); } #[test] From 1c629ade3a996d98302a2538397e0cbb62248b58 Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Wed, 4 Apr 2018 18:42:41 +0200 Subject: [PATCH 10/11] Codestyle and docs --- src/sys/resource.rs | 13 ++++++------- test/test_resource.rs | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/sys/resource.rs b/src/sys/resource.rs index 1b8f85f068..e815326e50 100644 --- a/src/sys/resource.rs +++ b/src/sys/resource.rs @@ -54,7 +54,7 @@ libc_enum!{ /// Get the current processes resource limits /// -/// A value of `None` corresponds to `RLIM_INFINITY`, which means there's no limit. +/// A value of None indicates that there's no limit. /// /// # Parameters /// @@ -64,11 +64,10 @@ libc_enum!{ /// /// ``` /// # use nix::sys::resource::{getrlimit, Resource}; -/// # fn main() { +/// /// let (soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap(); /// println!("current soft_limit: {:?}", soft_limit); /// println!("current hard_limit: {:?}", hard_limit); -/// # } /// ``` /// /// # References @@ -79,6 +78,7 @@ libc_enum!{ pub fn getrlimit(resource: Resource) -> Result<(Option, Option)> { let mut rlim: rlimit = unsafe { mem::uninitialized() }; let res = unsafe { libc::getrlimit(resource as c_int, &mut rlim as *mut _) }; + // TODO: use Option::filter after it has been stabilized Errno::result(res).map(|_| { (if rlim.rlim_cur != RLIM_INFINITY { Some(rlim.rlim_cur) } else { None }, if rlim.rlim_max != RLIM_INFINITY { Some(rlim.rlim_max) } else { None }) @@ -87,7 +87,7 @@ pub fn getrlimit(resource: Resource) -> Result<(Option, Option)> /// Set the current processes resource limits /// -/// A value of `None` corresponds to `RLIM_INFINITY`, which means there's no limit. +/// A value of None indicates that there's no limit. /// /// # Parameters /// @@ -100,11 +100,10 @@ pub fn getrlimit(resource: Resource) -> Result<(Option, Option)> /// /// ```no_run /// # use nix::sys::resource::{setrlimit, Resource}; -/// # fn main() { +/// /// let soft_limit = Some(1024); /// let hard_limit = None; /// setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap(); -/// # } /// ``` /// /// # References @@ -118,5 +117,5 @@ pub fn setrlimit(resource: Resource, soft_limit: Option, hard_limit: Opt rlim.rlim_max = hard_limit.unwrap_or(RLIM_INFINITY); let res = unsafe { libc::setrlimit(resource as c_int, &rlim as *const _) }; - Errno::result(res).map(drop) + Errno::result(res).map(|_| ()) } diff --git a/test/test_resource.rs b/test/test_resource.rs index 7ca6d3940c..4735d0a380 100644 --- a/test/test_resource.rs +++ b/test/test_resource.rs @@ -6,12 +6,12 @@ pub fn test_resource_limits_nofile() { // make sure the soft limit and hard limit are not equal let soft_limit = match soft_limit { - Some(nofile) => Some(nofile -1), + Some(nofile) => Some(nofile - 1), None => Some(1024), }; setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap(); - let (new_soft_limit, new_hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap(); + let (new_soft_limit, _new_hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap(); assert_eq!(new_soft_limit, soft_limit); } From f87978b4bb10c63d284111f9d6446c8b0d4601e1 Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Sat, 14 Apr 2018 18:47:55 +0200 Subject: [PATCH 11/11] Document Resource enum --- src/sys/resource.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/sys/resource.rs b/src/sys/resource.rs index e815326e50..7f8fa507d9 100644 --- a/src/sys/resource.rs +++ b/src/sys/resource.rs @@ -7,46 +7,67 @@ pub use libc::rlim_t; use {Errno, Result}; libc_enum!{ + /// A resource that limits apply to #[repr(i32)] pub enum Resource { // POSIX + /// This is the maximum size of the process's virtual memory (address space). The limit is specified in bytes, and is rounded down to the system page size. RLIMIT_AS, + /// This is the maximum size of a core file (see core(5)) in bytes that the process may dump. RLIMIT_CORE, + /// This is a limit, in seconds, on the amount of CPU time that the process can consume. RLIMIT_CPU, + /// This is the maximum size of the process's data segment (initialized data, uninitialized data, and heap). The limit is specified in bytes, and is rounded down to the system page size. RLIMIT_DATA, + /// This is the maximum size in bytes of files that the process may create. Attempts to extend a file beyond this limit result in delivery of a SIGXFSZ signal. RLIMIT_FSIZE, + /// This specifies a value one greater than the maximum file descriptor number that can be opened by this process. RLIMIT_NOFILE, + /// This is the maximum size of the process stack, in bytes. Upon reaching this limit, a SIGSEGV signal is generated. RLIMIT_STACK, // BSDs and Linux + /// This is the maximum number of bytes of memory that may be locked into RAM. This limit is in effect rounded down to the nearest multiple of the system page size. #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux", target_os = "openbsd"))] RLIMIT_MEMLOCK, + /// This is a limit on the number of extant process (or, more precisely on Linux, threads) for the real user ID of the calling process. #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux", target_os = "openbsd"))] RLIMIT_NPROC, + /// This is a limit (in bytes) on the process's resident set (the number of virtual pages resident in RAM). #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux", target_os = "openbsd"))] RLIMIT_RSS, // Android and Linux only + /// This is a limit on the combined number of flock(2) locks and fcntl(2) leases that this process may establish. #[cfg(any(target_os = "android", target_os = "linux"))] RLIMIT_LOCKS, + /// This is a limit on the number of bytes that can be allocated for POSIX message queues for the real user ID of the calling process. #[cfg(any(target_os = "android", target_os = "linux"))] RLIMIT_MSGQUEUE, + /// This specifies a ceiling to which the process's nice value can be raised using setpriority(2) or nice(2). The actual ceiling for the nice value is calculated as 20 - rlim_cur. #[cfg(any(target_os = "android", target_os = "linux"))] RLIMIT_NICE, + /// This specifies a ceiling on the real-time priority that may be set for this process using sched_setscheduler(2) and sched_setparam(2). #[cfg(any(target_os = "android", target_os = "linux"))] RLIMIT_RTPRIO, + /// This is a limit (in microseconds) on the amount of CPU time that a process scheduled under a real-time scheduling policy may consume without making a blocking system call. #[cfg(any(target_os = "android", target_os = "linux"))] RLIMIT_RTTIME, + /// This is a limit on the number of signals that may be queued for the real user ID of the calling process. Both standard and real-time signals are counted for the purpose of checking this limit. #[cfg(any(target_os = "android", target_os = "linux"))] RLIMIT_SIGPENDING, // Available on some BSD + /// The maximum number of kqueues this user id is allowed to create. #[cfg(target_os = "freebsd")] RLIMIT_KQUEUES, + /// The maximum number of pseudo-terminals this user id is allowed to create. #[cfg(target_os = "freebsd")] RLIMIT_NPTS, + /// The maximum size (in bytes) of socket buffer usage for this user. #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] RLIMIT_SBSIZE, + /// The maximum size (in bytes) of the swap space that may be reserved or used by all of this user id's processes. #[cfg(target_os = "freebsd")] RLIMIT_SWAP, }