diff --git a/crates/util/Cargo.toml b/crates/util/Cargo.toml index d1f3c0c70e..7ed25dd73f 100644 --- a/crates/util/Cargo.toml +++ b/crates/util/Cargo.toml @@ -56,7 +56,7 @@ dirs.workspace = true [target.'cfg(unix)'.dependencies] command-fds = "0.3.1" libc.workspace = true -nix = { workspace = true, features = ["user"] } +nix = { workspace = true, features = ["resource", "user"] } [target.'cfg(target_os = "macos")'.dependencies] mach2.workspace = true diff --git a/crates/util/src/util.rs b/crates/util/src/util.rs index 88d874696c..529abc10da 100644 --- a/crates/util/src/util.rs +++ b/crates/util/src/util.rs @@ -244,6 +244,39 @@ Error: Running Zed as root or via sudo is unsupported. } } +/// Raises the soft limit on open file descriptors without changing the hard limit. +/// +/// Call during startup, before spawning children that will inherit the limit. +#[cfg(unix)] +pub fn increase_open_file_limit() -> Result<()> { + use anyhow::Context as _; + use nix::sys::resource::{Resource::RLIMIT_NOFILE, getrlimit, setrlimit}; + + let (soft_limit, hard_limit) = getrlimit(RLIMIT_NOFILE).context("getrlimit(RLIMIT_NOFILE)")?; + // These are startup targets, not OS ceilings. Preserve higher inherited limits. + let target = if cfg!(target_os = "macos") { + 10_240 + } else { + 65_536 + }; + let mut requested_limit = hard_limit.min(target); + + while requested_limit > soft_limit { + let Err(error) = setrlimit(RLIMIT_NOFILE, requested_limit, hard_limit) else { + log::info!("raised open file soft limit from {soft_limit} to {requested_limit}"); + return Ok(()); + }; + + // Some systems enforce a ceiling below the reported hard limit. + if error != nix::errno::Errno::EINVAL || requested_limit == soft_limit + 1 { + return Err(error).context("setrlimit(RLIMIT_NOFILE)"); + } + requested_limit = soft_limit + (requested_limit - soft_limit) / 2; + } + + Ok(()) +} + #[cfg(unix)] fn load_shell_from_passwd() -> Result<()> { let buflen = match unsafe { libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) } { diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index d759241eeb..ec3198047c 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -299,6 +299,9 @@ fn main() { } ztracing::init(); + #[cfg(unix)] + util::increase_open_file_limit().log_err(); + let version = option_env!("ZED_BUILD_ID"); let app_commit_sha = option_env!("ZED_COMMIT_SHA").map(|commit_sha| AppCommitSha::new(commit_sha.to_string()));