diff --git a/src/config.rs b/src/config.rs index 0b26acffc..4d278aa4d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -55,6 +55,7 @@ pub struct Config { pub(crate) toolchain: String, pub(crate) build_cpu_limit: Option, pub(crate) include_default_targets: bool, + pub(crate) disable_memory_limit: bool, } impl Config { @@ -101,6 +102,7 @@ impl Config { toolchain: env("CRATESFYI_TOOLCHAIN", "nightly".to_string())?, build_cpu_limit: maybe_env("DOCS_RS_BUILD_CPU_LIMIT")?, include_default_targets: env("DOCSRS_INCLUDE_DEFAULT_TARGETS", true)?, + disable_memory_limit: env("DOCSRS_DISABLE_MEMORY_LIMIT", false)?, }) } } diff --git a/src/docbuilder/rustwide_builder.rs b/src/docbuilder/rustwide_builder.rs index fa915de38..902703776 100644 --- a/src/docbuilder/rustwide_builder.rs +++ b/src/docbuilder/rustwide_builder.rs @@ -11,6 +11,7 @@ use crate::utils::{copy_doc_dir, parse_rustc_version, CargoMetadata, GithubUpdat use crate::{db::blacklist::is_blacklisted, utils::MetadataPackage}; use crate::{Config, Context, Index, Metrics, Storage}; use docsrs_metadata::{Metadata, DEFAULT_TARGETS, HOST_TARGET}; +use failure::bail; use failure::ResultExt; use log::{debug, info, warn, LevelFilter}; use postgres::Client; @@ -309,6 +310,24 @@ impl RustwideBuilder { } let limits = Limits::for_crate(&mut conn, name)?; + #[cfg(target_os = "linux")] + if !self.config.disable_memory_limit { + let mem_info = procfs::Meminfo::new().context("failed to read /proc/meminfo")?; + let available = mem_info + .mem_available + .expect("kernel version too old for determining memory limit"); + if limits.memory() as u64 > available { + bail!("not enough memory to build {} {}: needed {} MiB, have {} MiB\nhelp: set DOCSRS_DISABLE_MEMORY_LIMIT=true to force a build", + name, version, limits.memory() / 1024 / 1024, available / 1024 / 1024 + ); + } else { + debug!( + "had enough memory: {} MiB > {} MiB", + limits.memory() / 1024 / 1024, + available / 1024 / 1024 + ); + } + } let mut build_dir = self.workspace.build_dir(&format!("{}-{}", name, version)); build_dir.purge()?;