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:🧵: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: e437b9d908/src/linux.rs (L207-L210)
 - ninja: https://github.com/ninja-build/ninja/pull/2174/files
 - dotnet: c4341d45ac/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:🧵:cgroups::quota
   4: std::sys::unix:🧵:available_parallelism
   5: std:🧵: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.
This commit is contained in:
Adam Casey 2022-11-16 09:26:56 +00:00
parent 63c748ee23
commit 04f1ead552

View File

@ -510,7 +510,7 @@ mod cgroups {
let limit = raw_quota.next()?;
let period = raw_quota.next()?;
match (limit.parse::<usize>(), period.parse::<usize>()) {
(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),
_ => {}
}