diff --git a/base/src/sys/linux/mod.rs b/base/src/sys/linux/mod.rs index dbd582b3d7..ea185c8161 100644 --- a/base/src/sys/linux/mod.rs +++ b/base/src/sys/linux/mod.rs @@ -569,6 +569,43 @@ pub fn max_open_files() -> Result { } } +/// Executes the given callback with extended soft limit of max number of open files. After the +/// callback executed, restore the limit. +pub fn call_with_extended_max_files( + callback: impl FnOnce() -> std::result::Result, +) -> Result> { + let cur_limit = max_open_files()?; + let new_limit = libc::rlimit64 { + rlim_cur: cur_limit.rlim_max, + ..cur_limit + }; + let needs_extension = cur_limit.rlim_cur < new_limit.rlim_cur; + if needs_extension { + set_max_open_files(new_limit)?; + } + + let r = callback(); + + // Restore the soft limit. + if needs_extension { + set_max_open_files(cur_limit)?; + } + + Ok(r) +} + +/// Set the soft and hard limits of max number of open files to the given value. +fn set_max_open_files(limit: libc::rlimit64) -> Result<()> { + // SAFETY: RLIMIT_NOFILE is known only to read a buffer of size rlimit64, and we have always + // rlimit64 allocated. + let res = unsafe { libc::setrlimit64(libc::RLIMIT_NOFILE, &limit) }; + if res == 0 { + Ok(()) + } else { + errno_result() + } +} + /// Moves the requested PID/TID to a particular cgroup pub fn move_to_cgroup(cgroup_path: PathBuf, id_to_write: Pid, cgroup_file: &str) -> Result<()> { use std::io::Write;