From: Pádraig Brady Date: Sun, 24 Aug 2025 10:41:01 +0000 (+0100) Subject: tests: nproc: fix false failure on some systems X-Git-Tag: v9.8~95 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4bfcf62f74b38d762ee06ceef582c326023635a9;p=thirdparty%2Fcoreutils.git tests: nproc: fix false failure on some systems * tests/nproc/nproc-quota.sh: Also simulate sched_getscheduler() as this will not be called on older or non linux, or may return ENOSYS on Alpine. Fixes https://bugs.gnu.org/79299 --- diff --git a/tests/nproc/nproc-quota.sh b/tests/nproc/nproc-quota.sh index 236a1a83bd..1c1bc1f515 100755 --- a/tests/nproc/nproc-quota.sh +++ b/tests/nproc/nproc-quota.sh @@ -19,6 +19,53 @@ . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src print_ver_ nproc require_root_ +require_gcc_shared_ + +# Replace sched_getscheduler() +cat > k.c <<'EOF' || framework_failure_ +#include +#include +#define __USE_GNU /* For SCHED_DEADLINE. */ +#include + +int +sched_getscheduler (pid_t pid) +{ + fclose (fopen ("preloaded","w")); /* marker for preloaded interception */ + FILE* policyf = fopen ("/proc/self/sched", "r"); + int policy; + #define fscanfmt fscanf /* Avoid syntax check. */ + if (pid == 0 && fscanfmt (policyf, "policy : %d", &policy) == 1) + { + switch (policy) + { + case 0: return SCHED_OTHER; + case 1: return SCHED_FIFO; + case 2: return SCHED_RR; + case 6: return SCHED_DEADLINE; + case -1: errno = EINVAL; return -1; + default: return SCHED_OTHER; + } + } + else + { + errno = ENOSYS; + return -1; + } +} +EOF + +# compile/link the interception shared library: +gcc_shared_ k.c k.so \ + || skip_ 'failed to build sched_getscheduler shared library' + +(export LD_PRELOAD=$LD_PRELOAD:./k.so + nproc) || fail=1 + +# Ensure our wrapper is in place and is called +# I.e., this test is restricted to new enough Linux systems +# as otherwise cpu_quota() will not call sched_getscheduler() +test -e preloaded || skip_ 'LD_PRELOAD interception failed' # We could look for modifiable cgroup quotas on the current system, # but that would be dangerous to modify and restore robustly. @@ -32,6 +79,7 @@ ROOT=cgroup mkdir -p $ROOT/sys/fs/cgroup/foo && touch $ROOT/sys/fs/cgroup/cgroup.controllers && echo '0::/foo' > $ROOT/proc/self/cgroup && + echo 'policy : 0' > $ROOT/proc/self/sched && echo 'max 100000' > $ROOT/sys/fs/cgroup/foo/cpu.max # ignored } || framework_failure_ @@ -39,7 +87,10 @@ nproc=$abs_top_builddir/src/nproc$EXEEXT cp --parents $(ldd $nproc | grep -o '/[^ ]*') $ROOT || skip_ 'Failed to copy nproc libs to chroot' cp $nproc $ROOT || framework_failure_ -chroot $ROOT /nproc --version || +cp k.so $ROOT || framework_failure_ + +NPROC() { LD_PRELOAD=$LD_PRELOAD:./k.so chroot $ROOT /nproc "$@"; } +NPROC --version || skip_ 'Failed to execute nproc in chroot' unset OMP_NUM_THEADS @@ -52,34 +103,45 @@ ncpus=$(nproc) || fail=1 # would then not match $ncpus if test "$ncpus" = "$(nproc --all)"; then echo 'max 100000' > $ROOT/sys/fs/cgroup/cpu.max && -test $(chroot $ROOT /nproc) -eq $ncpus || fail=1 +test $(NPROC) -eq $ncpus || fail=1 # Note Linux won't allow values > 1,000,000 (i.e., micro seconds) # so no point testing above that threshold ( for e.g $((1<<53)) ) echo "1000000 1" > $ROOT/sys/fs/cgroup/cpu.max && -test $(chroot $ROOT /nproc) -eq $ncpus || fail=1 +test $(NPROC) -eq $ncpus || fail=1 # Can't happen in real cgroup, but ensure we avoid divide by zero echo '100000 0' > $ROOT/sys/fs/cgroup/cpu.max && -test $(chroot $ROOT /nproc) -eq $ncpus || fail=1 +test $(NPROC) -eq $ncpus || fail=1 +echo '100000 100000' > $ROOT/sys/fs/cgroup/cpu.max && +test $(OMP_NUM_THREADS=$ncpus NPROC) -eq $ncpus || fail=1 + echo '100000 100000' > $ROOT/sys/fs/cgroup/cpu.max && -test $(OMP_NUM_THREADS=$ncpus chroot $ROOT /nproc) -eq $ncpus || fail=1 +echo 'policy : 1' > $ROOT/proc/self/sched && # No quota for SCHED_FIFO +test $(NPROC) -eq $ncpus || fail=1 +echo 'policy : 2' > $ROOT/proc/self/sched && # No quota for SCHED_RR +test $(NPROC) -eq $ncpus || fail=1 +echo 'policy : 6' > $ROOT/proc/self/sched && # No quota for SCHED_DEADLINE +test $(NPROC) -eq $ncpus || fail=1 +echo 'policy : -1' > $ROOT/proc/self/sched && # Unsupported +test $(NPROC) -eq $ncpus || fail=1 +echo 'policy : 0' > $ROOT/proc/self/sched # reset to SCHED_OTHER fi echo '40000 100000' > $ROOT/sys/fs/cgroup/cpu.max && -test $(chroot $ROOT /nproc) -eq 1 || fail=1 +test $(NPROC) -eq 1 || fail=1 echo '50000 100000' > $ROOT/sys/fs/cgroup/cpu.max && -test $(chroot $ROOT /nproc) -eq 1 || fail=1 +test $(NPROC) -eq 1 || fail=1 echo '100000 100000' > $ROOT/sys/fs/cgroup/cpu.max && -test $(chroot $ROOT /nproc) -eq 1 || fail=1 +test $(NPROC) -eq 1 || fail=1 echo '140000 100000' > $ROOT/sys/fs/cgroup/cpu.max && -test $(chroot $ROOT /nproc) -eq 1 || fail=1 +test $(NPROC) -eq 1 || fail=1 echo '1 1000000' > $ROOT/sys/fs/cgroup/cpu.max && -test $(chroot $ROOT /nproc) -eq 1 || fail=1 +test $(NPROC) -eq 1 || fail=1 if test $ncpus -gt 1; then echo '150000 100000' > $ROOT/sys/fs/cgroup/cpu.max && -test $(chroot $ROOT /nproc) -eq 2 || fail=1 +test $(NPROC) -eq 2 || fail=1 echo '150000 100000' > $ROOT/sys/fs/cgroup/cpu.max && -test $(OMP_THREAD_LIMIT=10 chroot $ROOT /nproc) -eq 2 || fail=1 +test $(OMP_THREAD_LIMIT=10 NPROC) -eq 2 || fail=1 fi Exit $fail