mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-03-06 13:05:04 +02:00
* tests/du/move-dir-while-traversing.sh: Expand the work to avoid a false failure where du completes before the directory is moved. Also expand the timeout to our more standard 10s to avoid the "directory mover" being killed before du processes the directory. This doesn't perceptibly impact the run time of the test. Reported by Bruno Haible on a CentOS 7 system.
99 lines
3.2 KiB
Bash
Executable File
99 lines
3.2 KiB
Bash
Executable File
#!/bin/sh
|
|
# Trigger a failed assertion in coreutils-8.9 and earlier.
|
|
|
|
# Copyright (C) 2011-2025 Free Software Foundation, Inc.
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
|
|
print_ver_ du
|
|
require_trap_signame_
|
|
|
|
# We use a python-inotify script, so...
|
|
python -m pyinotify -h > /dev/null \
|
|
|| skip_ 'python inotify package not installed'
|
|
|
|
# Move a directory "up" while du is processing its sub-directories.
|
|
# While du is processing a hierarchy .../B/C/D/... this script
|
|
# detects when du opens D/, and then moves C/ "up" one level
|
|
# so that it is a sibling of B/.
|
|
# Given the inherent race condition, we have to add enough "weight"
|
|
# under D/ so that in most cases, the monitor performs the single
|
|
# rename syscall before du finishes processing the subtree under D/.
|
|
|
|
cat <<'EOF' > inotify-watch-for-dir-access.py
|
|
#!/usr/bin/env python
|
|
import pyinotify as pn
|
|
import os,sys
|
|
|
|
dir = sys.argv[1]
|
|
dest_parent = os.path.dirname(os.path.dirname(dir))
|
|
dest = os.path.join(dest_parent, os.path.basename(dir))
|
|
|
|
class ProcessDir(pn.ProcessEvent):
|
|
|
|
def process_IN_OPEN(self, event):
|
|
os.rename(dir, dest)
|
|
sys.exit(0)
|
|
|
|
def process_default(self, event):
|
|
pass
|
|
|
|
wm = pn.WatchManager()
|
|
notifier = pn.Notifier(wm)
|
|
wm.watch_transient_file(dir, pn.IN_OPEN, ProcessDir)
|
|
sys.stdout.write('started\n')
|
|
sys.stdout.flush()
|
|
notifier.loop()
|
|
EOF
|
|
chmod a+x inotify-watch-for-dir-access.py
|
|
|
|
t=T/U
|
|
mkdir d2 || framework_failure_
|
|
long=d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z
|
|
# One iteration of this loop creates a tree with which
|
|
# du sometimes completes its traversal before the above rename.
|
|
# Five iterations was not enough in 2 of 7 "make -j20 check" runs on a
|
|
# 6/12-core system. However, using "10", I saw no failure in 20 trials.
|
|
# 2011 this was set at 50, 2025 this was set at 99
|
|
for i in $(seq 99); do
|
|
mkdir -p $t/3/a/b/c/$i/$long || framework_failure_
|
|
done
|
|
|
|
# Terminate any background cp process
|
|
cleanup_() { kill $pid 2>/dev/null && wait $pid; }
|
|
|
|
# Prohibit suspension, which could otherwise cause a timeout-induced FP failure.
|
|
trap '' TSTP
|
|
|
|
timeout 10 ./inotify-watch-for-dir-access.py $t/3/a/b > start-msg & pid=$!
|
|
|
|
# Wait for the watcher to start...
|
|
nonempty() { sleep $1; test -s start-msg; }
|
|
retry_delay_ nonempty .1 5 || fail=1
|
|
|
|
# The above watches for an IN_OPEN event on $t/3/a/b,
|
|
# and when it triggers, moves the parent, $t/3/a, up one level
|
|
# so it's directly under $t.
|
|
|
|
# Before coreutils-8.10, du would abort.
|
|
returns_ 1 du -a $t d2 2> err || fail=1
|
|
|
|
# check for the new diagnostic
|
|
printf "du: fts_read failed: $t/3/a/b: No such file or directory\n" > exp \
|
|
|| fail=1
|
|
compare exp err || fail=1
|
|
|
|
Exit $fail
|