Skip to content

Commit f523850

Browse files
committed
Don't queue 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 ```
1 parent cc1b0c7 commit f523850

File tree

2 files changed

+23
-0
lines changed

2 files changed

+23
-0
lines changed

src/config.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ pub struct Config {
5555
pub(crate) toolchain: String,
5656
pub(crate) build_cpu_limit: Option<u32>,
5757
pub(crate) include_default_targets: bool,
58+
pub(crate) disable_memory_limit: bool,
5859
}
5960

6061
impl Config {
@@ -101,6 +102,7 @@ impl Config {
101102
toolchain: env("CRATESFYI_TOOLCHAIN", "nightly".to_string())?,
102103
build_cpu_limit: maybe_env("DOCS_RS_BUILD_CPU_LIMIT")?,
103104
include_default_targets: env("DOCSRS_INCLUDE_DEFAULT_TARGETS", true)?,
105+
disable_memory_limit: env("DOCSRS_DISABLE_MEMORY_LIMIT", false)?,
104106
})
105107
}
106108
}

src/docbuilder/rustwide_builder.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::utils::{copy_doc_dir, parse_rustc_version, CargoMetadata, GithubUpdat
1111
use crate::{db::blacklist::is_blacklisted, utils::MetadataPackage};
1212
use crate::{Config, Context, Index, Metrics, Storage};
1313
use docsrs_metadata::{Metadata, DEFAULT_TARGETS, HOST_TARGET};
14+
use failure::bail;
1415
use failure::ResultExt;
1516
use log::{debug, info, warn, LevelFilter};
1617
use postgres::Client;
@@ -309,6 +310,26 @@ impl RustwideBuilder {
309310
}
310311

311312
let limits = Limits::for_crate(&mut conn, name)?;
313+
#[cfg(target_os = "linux")]
314+
if !self.config.disable_memory_limit {
315+
let mem_info = procfs::Meminfo::new().context("failed to read /proc/meminfo")?;
316+
let available = mem_info.mem_available.unwrap_or(
317+
// Assume about half of cached memory can be reclaimed without thrashing.
318+
// This is a terrible hack.
319+
mem_info.mem_free + mem_info.cached / 2,
320+
);
321+
if limits.memory() as u64 > available {
322+
bail!("not enough memory to build {} {}: needed {} MiB, have {} MiB\nhelp: set DOCSRS_DISABLE_MEMORY_LIMIT=true to force a build",
323+
name, version, limits.memory() / 1024 / 1024, available / 1024 / 1024
324+
);
325+
} else {
326+
debug!(
327+
"had enough memory: {} MiB > {} MiB",
328+
limits.memory() / 1024 / 1024,
329+
available / 1024 / 1024
330+
);
331+
}
332+
}
312333

313334
let mut build_dir = self.workspace.build_dir(&format!("{}-{}", name, version));
314335
build_dir.purge()?;

0 commit comments

Comments
 (0)