From 04f1ead55243c895da7c3703e2daca319f381124 Mon Sep 17 00:00:00 2001 From: Adam Casey Date: Wed, 16 Nov 2022 09:26:56 +0000 Subject: [PATCH] available_parallelism: Handle 0 cfs_period_us There seem to be some scenarios where `cpu.cfs_period_us` can contain `0` This causes a panic when calling `std::thread::available_parallelism()` as is done so from binaries built by `cargo test`, which was how the issue was discovered. I don't feel like `0` is a good value for `cpu.cfs_period_us`, but I also don't think applications should panic if this value is seen. This case is handled by other projects which read this information: - num_cpus: https://github.com/seanmonstar/num_cpus/blob/e437b9d9083d717692e35d917de8674a7987dd06/src/linux.rs#L207-L210 - ninja: https://github.com/ninja-build/ninja/pull/2174/files - dotnet: https://github.com/dotnet/runtime/blob/c4341d45acca3ea662cd8d71e7d71094450dd045/src/coreclr/pal/src/misc/cgroup.cpp#L481-L483 Before this change, this panic could be seen in environments setup as described above: ``` $ RUST_BACKTRACE=1 cargo test Finished test [unoptimized + debuginfo] target(s) in 3.55s Running unittests src/main.rs (target/debug/deps/x-9a42e145aca2934d) thread 'main' panicked at 'attempt to divide by zero', library/std/src/sys/unix/thread.rs:546:70 stack backtrace: 0: rust_begin_unwind 1: core::panicking::panic_fmt 2: core::panicking::panic 3: std::sys::unix::thread::cgroups::quota 4: std::sys::unix::thread::available_parallelism 5: std::thread::available_parallelism 6: test::helpers::concurrency::get_concurrency 7: test::console::run_tests_console 8: test::test_main 9: test::test_main_static 10: x::main at ./src/main.rs:1:1 11: core::ops::function::FnOnce::call_once at /tmp/rust-1.64-1.64.0-1/library/core/src/ops/function.rs:248:5 note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. error: test failed, to rerun pass '--bin local-rabmq-amqpprox' ``` I've tested this change in an environment which has the bad setup and rebuilding the test executable against a fixed std library fixes the panic. --- library/std/src/sys/unix/thread.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index c1d30dd9d52..9125174efab 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -510,7 +510,7 @@ mod cgroups { let limit = raw_quota.next()?; let period = raw_quota.next()?; match (limit.parse::(), period.parse::()) { - (Ok(limit), Ok(period)) => { + (Ok(limit), Ok(period)) if period > 0 => { quota = quota.min(limit / period); } _ => {} @@ -570,7 +570,7 @@ mod cgroups { let period = parse_file("cpu.cfs_period_us"); match (limit, period) { - (Some(limit), Some(period)) => quota = quota.min(limit / period), + (Some(limit), Some(period)) if period > 0 => quota = quota.min(limit / period), _ => {} }