Jon Turney via Cygwin-apps wrote:
On 15/09/2024 16:11, Jon Turney via Cygwin-apps wrote:
On 13/09/2024 18:33, Christian Franke via Cygwin-apps wrote:
I would like to contribute stress-ng. Also present in Debian, Fedora, FreeBSD, Ubuntu, ...

I was thinking about adding a step to our CI to run stress-ng, as it seems quite good at finding some kinds of regressions.

I wonder if you could suggest a suitable set of options to invoke it with?


Attached is an enhanced version of my local script used to test stress-ng before packaging. I agree that it should provide some more comments :-)

Try
  ./cygstress -n CI
to see a selection of tests for CI. Remove -n to run these (~ 5min). It would also be possible to run the tests with a single stress-ng command.

The tests which detected Cygwin bugs that are already fixed are included, see comments "fixed in Cygwin ...".

Use WORK (or FAIL) instead of CI to run all working (or failing) tests. See comments "TODO Cygwin: ..." for brief info about the failures. See three links for testcases posted to ML.

Tests are intentionally run separately because failing tests sometimes hang and may even ignore SIGKILL. Therefore an external tool is used, pskill from Sysinternals Suite is the default.

--
Regards,
Christian

#!/bin/bash
#
# Run stress-ng on Cygwin
#
# Copyright 2025 Christian Franke
#
# SPDX-License-Identifier: BSD-3-Clause
#

set -e -o pipefail

usage()
{
  cat <<EOF
Usage: ${0##*/} [OPTION...] {CI|WORK|FAIL|test...}

  -n        print commands only (dry-run)
  -f        force execution of tests tagged 'heavy' or 'admin'
  -c LIST   set CPU affinity to LIST
  -k PATH   tool to stop hanging tests [default: pskill]
  -s PATH   stress-ng executable [default: stress-ng]
  -t N      run each test for at least N seconds [default: 5]
  -w N      start N workers for each test [default: 2]

  CI        run all tests tagged CI
  WORK      run all tests tagged WORKS
  FAIL      run all tests tagged FAILS
  test...   run invidual test(s) (may require '-f')
EOF
  exit 1
}

# Tags:
# WORKS: works on Cygwin (3.7.0-0.43.g779e46b5b3ee)
# WORKS,CI: possibly suitable subset for Cygwin CI test.
# FAILS: fails on Cygwin, see "TODO Cygwin" for details.
# heavy: heavy resource usage, may work, hang, freeze desktop, require reset, 
...
# admin: requires administrator, may work or not, may be 'heavy' or not.
# -----: unsupported due to missing API, library, declaration, ...

stress_tests='
# TEST [ARGS]   # Tag       # Comment
  access        # FAILS     # TODO undecided: "access 004 on chmod mode 400 
failed: 13 (Permission denied)"
  acl           # WORKS,CI  # (fixed in stress-ng 0.18.12)
  affinity      # WORKS
  af-alg        # -----     # requires AF_ALG
  aio           # WORKS
  aiol          # -----     # requires io_setup(2), io_submit(2), ...
  alarm         # WORKS,CI
  apparmor      # -----
  atomic        # WORKS

  bad-altstack  # WORKS
  bad-ioctl     # -----
  besselmath    # WORKS
  bigheap       # heavy
  binderfs      # -----
  bind-mount    # -----
  bitonicsort   # WORKS
  bitops        # WORKS
  branch        # WORKS
  brk           # heavy     # allocates memory until OOM
  bsearch       # WORKS
  bubblesort    # WORKS

  cache         # WORKS
  cacheline     # WORKS
  cachehammer   # WORKS
  cap           # -----
  cgroup        # -----
  chattr        # -----
  chdir         # WORKS,CI
  chmod         # WORKS,CI
  chown         # FAILS     # TODO undecided: "fchown failed, errno=22 (Invalid 
argument)"
  chroot        # admin
  clock         # WORKS,CI  # (fixed in stress-ng 0.18.12: "timer_create failed 
for timer ...
                            #  ... ''CLOCK_THREAD_CPUTIME_ID'', errno=134")
  clone         # -----
  close         # FAILS     # TODO Cygwin: close(2) is not thread-safe
  context       # WORKS,CI  # (fixed in Cygwin 3.6.0: signals lost after 
swapcontext)
  copy-file     # -----
  cpu           # WORKS
  cpu-online    # -----
  cpu-sched     # FAILS     # TODO undecided: "child died: signal 9 ''SIGKILL''"
                            # (fixed in Cygwin 3.6.0: signals lost after 
SIGSTOP)
  crypt         # WORKS     # uses libcrypt
  cyclic        # admin

  daemon        # WORKS
  dccp          # -----
  dekker        # WORKS
  dentry        # WORKS
  dev           # FAILS     # TODO Cygwin: "*** fatal error in forked process - 
pthread_mutex::_fixup_after_fork () ...
                            # ... doesn''t understand PROCESS_SHARED mutex''s"
  dev-shm       # -----
  dfp           # WORKS
  dir           # WORKS
  dirdeep       # heavy     # creates deep dir tree
  dirmany       # heavy     # creates many dirs/files
  dnotify       # -----
  dup           # WORKS,CI
  dynlib        # -----

  easy-opcode   # WORKS
  eigen         # WORKS
  efivar        # -----
  enosys        # -----
  env           # heavy     # creates very large environment until OOM
  epoll         # -----
  eventfd       # -----
  exec          # WORKS,CI
  exit-group    # -----
  expmath       # WORKS

  factor        # WORKS     # uses libgmp
  fallocate     # WORKS,CI
  fanotify      # -----
  far-branch    # WORKS
  fault         # WORKS
  fcntl         # FAILS     # TODO Cygwin: "ftruncate failed, errno=21 (Is a 
directory)", please see:
                            #   
https://sourceware.org/pipermail/cygwin/2025-April/257871.html
  fd-fork       # WORKS,CI
  fd-race       # -----     # TODO stress-ng: drop Linux restriction (but then 
it FAILS)
  fibsearch     # WORKS
  fiemap        # -----
  fifo          # WORKS
  file-ioctl    # WORKS,CI
  filename      # FAILS     # TODO Cygwin: creates files Cygwin cannot remove 
later, please see:
                            #   
https://sourceware.org/pipermail/cygwin/2024-September/256451.html
  filename --filename-opts posix # WORKS,CI # restricts filenames to POSIX 
charset
# filerace      # WORKS     # TODO this script: add in stress-ng >0.18.12
  flipflop      # WORKS
  flock         # WORKS,CI
  flushcache    # WORKS
  fma           # WORKS
  fork          # WORKS,CI
  forkheavy     # heavy     # forks until process table is full
  fp            # WORKS,CI
  fp-error      # WORKS,CI
  fpunch        # FAILS     # TODO this script: fixed in stress-ng >0.18.12
  fractal       # WORKS
  fsize         # heavy     # creates large files until disk is full
  fstat         # WORKS,CI
  full          # -----     # requires pread/pwrite() working on /dev/full
  funccall      # WORKS
  funcret       # WORKS
  futex         # -----

  get           # WORKS
  getdent       # -----
  getrandom     # -----
  goto          # WORKS
  gpu           # -----

  handle        # -----     # requires name/open_by_handle_at(2)
  hash          # WORKS
  hdd           # WORKS
  heapsort      # WORKS     # uses libbsd
  hrtimers      # WORKS,CI  # (fixed in Cygwin 3.5.7: "timer_delete failed")
  hsearch       # WORKS
  hyperbolic    # WORKS

  icache        # WORKS
  icmp-flood    # -----     # requires "struct icmphdr", ... in <netinet/*.h>
  idle-page     # -----     # requires /sys/kernel/mm/page_idle/bitmap
  inode-flags   # -----
  inotify       # -----     # requires inotify_*(2)
  insertionsort # WORKS
  intmath       # WORKS
  io            # WORKS
  iomix         # WORKS
  ioport        # -----
  ioprio        # -----
  io-uring      # -----
  ipsec-mb      # -----     # requires libipsec-mb
  itimer        # WORKS,CI

  jpeg          # WORKS     # uses libjpeg
  judy          # -----     # requires libJudy (ORPHANED)

  kcmp          # -----
  key           # -----
  kill          # WORKS,CI
  klog          # -----
  kvm           # -----

  l1cache       # -----     # requires /sys/devices/system/cpu
  l1cache --l1cache-line-size 32768 --l1cache-ways 8 --l1cache-sets 1 # WORKS
  landlock      # -----
  lease         # -----
  led           # -----
  link          # WORKS,CI
  list          # WORKS
  llc-affinity  # WORKS
  loadavg       # WORKS
  locka         # WORKS
  lockbus       # WORKS
  lockf         # WORKS,CI  # (fixed in Cygwin 3.5.5: "NtCreateEvent(lock): 
0xC000003" and ...
                            #  "can''t handle more than 910 locks per file")
  lockmix       # WORKS
  lockofd       # -----
  logmath       # WORKS,CI  # (fixed in Cygwin 3.5.5: signal handler destroys 
long double values)
  longjmp       # WORKS,CI  # (fixed in Cygwin 3.5.5: signals lost during 
setjmp or longjmp)
  loop          # -----
  lsearch       # WORKS
  lsm           # -----

  madvise       # WORKS
  malloc        # WORKS,CI
  matrix        # WORKS
  matrix-3d     # WORKS
  mcontend      # WORKS
  membarrier    # -----
  memcpy        # WORKS,CI  # (fixed in Cygwin >3.6.0: crash due to set DF in 
signal handler)
  memfd         # -----
  memhotplug    # -----
  memrate       # WORKS
  memthrash     # WORKS
  mergesort     # WORKS     # uses libbsd
  metamix       # FAILS     # TODO Cygwin: "fdatasync on 
./tmp-stress-ng-metamix-*/... failed, errno=13"
  mincore       # -----
  min-nanosleep # WORKS
  misaligned    # WORKS
  mknod         # -----
  mlock         # WORKS
  mlockmany     # heavy     # requires --pathological
  mmap          # WORKS,CI
  mmapaddr      # WORKS
  mmapfork      # WORKS
  mmapfiles     # WORKS
  mmapfixed     # WORKS
  mmaphuge      # -----
  mmapmany      # WORKS
  mmaptorture   # heavy
  module        # -----
  monte-carlo   # WORKS
  mpfr          # WORKS     # uses libmpfr
  mprotect      # FAILS     # TODO Cygwin: crashes or hangs
  mq            # FAILS     # TODO Cygwin: "mq_receive failed, errno=1"
                            # (fixed in Cygwin 3.5.6: crash on invalid mq fd)
  mremap        # -----
  mseal         # -----
  msg           # WORKS
  msync         # WORKS
  msyncmany     # WORKS
  mtx           # WORKS
  munmap        # -----
  mutex         # WORKS

  nanosleep     # FAILS     # TODO undecided: "detected 1 unexpected nanosleep 
underruns"
  netdev        # -----
  netlink-proc  # -----
  netlink-task  # -----
  nice          # heavy     # TODO Cygwin: may change nice value of other 
processes
  nop           # WORKS
  null          # WORKS
  numa          # -----

  oom-pipe      # -----
  opcode        # -----
  open          # WORKS,CI

  pagemove      # -----
  pageswap      # -----
  pci           # -----
  personality   # -----
  peterson      # WORKS
  physmmap      # -----
  physpage      # -----
  pidfd         # -----
  ping-sock     # -----
  pipe          # WORKS,CI
  pipeherd      # heavy     # many forks, may freeze desktop
  pkey          # -----
  plugin        # -----
  poll          # WORKS
  powmath       # WORKS
  prctl         # -----
  prefetch      # WORKS
  prime         # WORKS     # uses libgmp
  prio-inv      # -----     # requires <pthread_nt.h>
  priv-instr    # FAILS     # TODO Cygwin: crashes or hangs, please see:
                            #   
https://sourceware.org/pipermail/cygwin/2025-March/257726.html
  procfs        # -----     # TODO stress-ng: support /proc subset of Cygwin
  pseek         # WORKS,CI  # (fixed in Cygwin 3.5.5: "pread: Bad file 
descriptor")
  pthread       # WORKS,CI
  ptr-chase     # WORKS
  ptrace        # -----
  pty           # FAILS     # TODO stress-ng: do not require 
tcdrain/tcflow/TIOCINQ for pty, or ...
                            # ... TODO Cygwin: implement tcdrain/tcflow/TIOCINQ 
for pty :-)
                            # (fixed in Cygwin 3.7.0: "No pty allocated, 
errno=0")
  qsort         # WORKS
  quota         # -----

  race-sched    # WORKS
  radixsort     # WORKS     # uses libbsd
  ramfs         # -----
  rawdev        # -----
  randlist      # WORKS
  rawsock       # -----
  rawpkt        # -----     # requires <linux/if_packet.h>, ...
  rawudp        # -----
  rdrand        # WORKS
  readahead     # -----
  reboot        # -----
  regex         # WORKS
  regs          # WORKS
  remap         # -----
  rename        # WORKS,CI
  resched       # heavy
  resources     # heavy
  revio         # WORKS
  ring-pipe     # WORKS
  rlimit        # heavy
  rmap          # WORKS
  rotate        # WORKS
  rseq          # -----
  rtc           # -----     # requires /dev/rtc

  schedmix      # WORKS
  schedpolicy   # WORKS,CI
  sctp          # -----
  seal          # -----
  seccomp       # -----
  secretmem     # -----
  seek          # WORKS,CI
  sem           # FAILS     # TODO Cygwin: "instance 0 corrupted bogo-ops 
counter, 556328 vs 556327"
  sem-sysv      # FAILS     # TODO Cygwin: "aborted early, out of system 
resources"
  sendfile      # -----     # requires sendfile(2)
  session       # WORKS
  set           # FAILS     # TODO stress-ng: "setrlimit failed, ..., expected 
-EPERM, instead got errno=22 (Invalid argument)"
  shellsort     # WORKS
  shm           # WORKS,CI
  shm-sysv      # -----     # requires shmat(2), smdt(2)
  sigabrt       # WORKS,CI
  sigbus        # FAILS     # TODO Cygwin: "ftruncate file to a single page 
failed, errno=13 (Permission denied)"
  sigchld       # FAILS     # TODO Cygwin: hangs
  sigfd         # -----     # TODO stress-ng: drop restriction to glibc (WORKS 
then)
  sigfpe        # FAILS     # TODO undecided: "got SIGFPE error 15 
(FPE_INTDEV), expecting 20 (FPE_FLTRES)"
  sighup        # WORKS,CI
  sigill        # FAILS     # TODO Cygwin: "terminated on signal: 11", possibly 
similar to "priv-instr"
  sigio         # -----     # requires O_ASYNC
  signal        # WORKS,CI
  signest       # FAILS     # TODO Cygwin: "terminated on signal: 11"
  sigpending    # WORKS,CI
  sigpipe       # WORKS,CI
  sigq          # WORKS,CI
  sigrt         # WORKS,CI
  sigsegv       # FAILS     # TODO Cygwin: crashes or hangs, possibly similar 
to "priv-instr"
  sigsuspend    # WORKS,CI
  sigtrap       # WORKS,CI
  sigurg        # WORKS,CI
  sigvtalrm     # WORKS,CI
  sigxcpu       # FAILS     # TODO stress-ng: "setrlimit failed, errno=22 
(Invalid argument)"
  sigxfsz       # FAILS     # TODO stress-ng: "setrlimit failed, errno=22 
(Invalid argument)"
  skiplist      # WORKS
  sleep         # WORKS,CI
  smi           # -----
  sock          # WORKS
  sockabuse     # WORKS
  sockdiag      # -----
  sockfd        # -----
  sockmany      # heavy
  sockpair      # WORKS
  softlockup    # admin
  sparsematrix  # WORKS
  spawn         # heavy     # TODO Cygwin: "NNN spawns failed (100.00%)", may 
crash other processes
  spinmem       # WORKS
  splice        # -----
  stack         # heavy
  stackmmap     # WORKS
  statmount     # -----
  str           # WORKS
  stream        # WORKS     # TODO stress-ng: get --stream-l3-size for 
/proc/cpuinfo
  swap          # -----
  switch        # WORKS
  symlink       # WORKS,CI
  sync-file     # -----
  syncload      # WORKS
  sysbadaddr    # heavy
  syscall       # FAILS     # TODO Cygwin: "terminated on signal: 11"
  sysinfo       # WORKS
  sysinval      # -----
  sysfs         # -----

  tee           # -----     # requires tee(2)
  timer         # WORKS,CI
  timerfd       # heavy     # TODO undecided: may freeze desktop
  time-warp     # WORKS
  tlb-shootdown # heavy
  tmpfs         # -----     # requires tmpfs filesystem
  touch         # WORKS
  tree          # WORKS     # (fixed in Cygwin >3.6.0: crash due to set DF in 
signal handler, see also "memcpy")
  trig          # WORKS
  tsc           # WORKS
  tsearch       # WORKS
  tun           # -----

  udp           # WORKS
  udp-flood     # -----     # requires AF_PACKET
  umask         # WORKS
  umount        # -----
  unlink        # WORKS,CI
  unshare       # -----
  uprobe        # -----
  urandom       # WORKS
  userfaultfd   # -----
  usersyscall   # -----
  utime         # WORKS,CI

  vdso          # -----
  veccmp        # WORKS
  vecfp         # WORKS
  vecmath       # WORKS
  vecshuf       # WORKS
  vecwide       # WORKS
  verity        # -----
  vfork         # WORKS
  vforkmany     # heavy     # forks until process table is full
  vm            # WORKS,CI
  vm-addr       # WORKS
  vm-rw         # -----
  vm-segv       # WORKS
  vm-splice     # -----
  vma           # WORKS
  vnni          # WORKS

  wait          # FAILS     # TODO Cygwin: hangs in few cases
  waitcpu       # WORKS
  watchdog      # -----
  wcs           # WORKS
  workload      # WORKS,CI  # (fixed in Cygwin 3.5.5: hang in mq_send/receive)

  x86cpuid      # WORKS
  x86syscall    # -----
  xattr         # FAILS     # TODO Cygwin: "fsetxattr succeeded unexpectedly, 
created ...
                            # "... attribute with size greater than permitted 
size, errno=61"
  yield         # WORKS

  zero          # WORKS,CI
  zlib          # WORKS     # uses libz
  zombie        # WORKS,CI
'

# SIGKILL may not work if stress-ng hangs.
# Use Sysinternals 'pskill' as no 'killall --force' is available,
killall_force="pskill"

stress_ng="stress-ng"
timeout=5; workers=2
dryrun=false; force=false
taskset=

while :; do case $1 in
  -c) shift; taskset=$1 ;;
  -f) force=true ;;
  -k) shift; killall_force=$1 ;;
  -n) dryrun=true ;;
  -s) shift; stress_ng=$1 ;;
  -t) shift; timeout=$1 ;;
  -w) shift; workers=$1 ;;
  -*) usage ;;
  *) break ;;
esac; shift || usage; done

run_ci=false; run_work=false; run_fail=false
run_tests=

for t in "$@"; do case $t in
  CI) run_ci=true ;;  WORK) run_work=true ;; FAIL) run_fail=true ;;
  [a-z]*[a-z]) run_tests+=" $t" ;;
  *) usage ;;
esac; done
$run_ci || $run_work || $run_fail || [ ${run_tests:+t} ] || usage

command -V "$stress_ng" >/dev/null || exit 1
command -V "$killall_force" >/dev/null || exit 1

stress_ng_name=${stress_ng##*/}
tempdir=${TMP:-/tmp}

find_stress()
{
  local p=$(procps -C "$stress_ng_name" -o pid,ppid,s,pri,ni,tt,start,time,args 
--sort pid)
  test "$(wc -l <<< "$p")" -gt 1 || return 1
  echo "$p"
}

stop_stress()
{
  echo '$' "$killall_force" "$stress_ng_name"
  "$killall_force" "$stress_ng_name" ||:
}

total=0
fails=0

# stress TEST [OPTION...]
stress()
{
  local name=$1
  shift || return 1

  local td="$tempdir/stress-ng.$$.$total.d"
  local cmd=("$stress_ng" -v -M --oomable --timestamp --verify --temp-path 
"$td" -t "$timeout")
  test -z "$taskset" || cmd+=(--taskset "$taskset")
  cmd+=(--"$name" "$workers" "$@")

  echo '$' "${cmd[@]}"
  ! $dryrun || return 0

  (
    t=$(date +%s); : $((t += timeout + 30)); sleep 1
    while [ "$(date +%s)" -lt "$t" ]; do sleep 1; done
    stop_stress & # TODO: without '&', 'exit 0' below is not reached (Hmm...)
    exit 0
  ) &
  local watchdog=$!
  trap "kill $watchdog 2>/dev/null ||:; exit 130" SIGINT SIGTERM

  mkdir "$td"
  local rc=0
  "${cmd[@]}" || rc=$?

  kill $watchdog 2>/dev/null ||:
  trap - SIGINT SIGTERM

  local ok=true
  if wait $watchdog; then
    echo ">>> FAILURE: $name" "$@" "(command hangs)"
    sleep 2
    ok=false
  fi

  local n=0 p
  if p=$(find_stress); then
    echo ">>> FAILURE: $name" "$@" "(processes left, exit status $rc):"
    echo "$p"
    stop_stress
    sleep 2
    ok=false
  fi

  if ! rmdir "$td" 2>/dev/null; then
    echo ">>> FAILURE: $name" "$@" "(files left in '$td', exit status $rc)"
    ok=false
  fi

  if ! $ok; then
    echo
    return 1
  fi
  if [ $rc != 0 ]; then
    echo ">>> FAILURE: $name" "$@" "(exit status $rc)"; echo
    return 1
  fi
  echo ">>> SUCCESS: $name" "$@" ""; echo
}

if p=$(find_stress); then
  echo "*** Other $stress_ng_name processes are still running:"
  echo "$p"
  $dryrun || exit 1
fi

while read; do
  args=${REPLY#*|}
  name=${args%% *}
  run_this=false
  for t in $run_tests; do if [ "$t" = "$name" ]; then
    run_this=true; break
  fi; done

  tag=${REPLY%%|*}
  case $tag in
    FAILS) $run_this || $run_fail || continue ;;
    WORKS) $run_this || $run_work || continue ;;
    WORKS,CI) $run_this || $run_work || $run_ci || continue ;;
    -----) $run_this || continue ;;
    admin|heavy)
      $run_this || continue
      if ! $force; then
        echo ">>> SKIPPED $name (tagged '$tag', use '-f' to override)"; echo
        continue
      fi ;;
    *) echo "*** syntax error: '$REPLY'"; exit 1 ;;
  esac

  : $((++total))
  stress $args ||: $((++fails))
done <<<"$(
  sed -E \
    -e 's/^ *([-0-9a-z]+)( +-[^#]*[^ #])? +# 
*(FAILS|WORKS(,CI)?|admin|heavy|-----) *(#.*)?$/\3|\1\2/' \
    -e '/^ *(#.*)?$/d' \
    <<<"$stress_tests"
)"

if [ $fails -ne 0 ]; then
  echo ">>> FAILURE: $fails of $total stress test(s) failed"
  exit 1
fi
echo ">>> SUCCESS: All $total stress test(s) succeeded"
exit 0

Reply via email to