From df50879a2d6e8c489e7248c63c5a8b6f16c508ce Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Mon, 15 Feb 2021 01:45:00 -0500 Subject: [PATCH] Don't execute a build when not enough memory is available Example error: ``` 2021/02/15 01:43:12 [INFO] docs_rs::docbuilder::rustwide_builder: building package regex 1.3.1 Error: Building documentation failed Caused by: not enough memory to build regex 1.3.1: needed 3072 MiB, have 2909 MiB help: set DOCSRS_DISABLE_MEMORY_LIMIT to force a build ``` --- src/config.rs | 2 ++ src/docbuilder/rustwide_builder.rs | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) 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()?;