Hi,
I noticed that when chown'ing a directory tree recursively with many
files sometimes chown will exit 1 and report ENOENT errors. This happens
when looping over the directory results from readdir() and in a parallel
another process removes a file before the code then calls stat(),
chmod() or whatever syscalls the command has to do for the given filename.
Since such race is expected the coreutils should not treat this as error
and just ignore them instead. That way a parallel removal of a file will
not make the commands return exit code 1 and thus possibility break
scripts. Of course this should only apply to files or directories under
the main path given as input, i.e. chmod -R dest should still fail with
ENOENT when dest does not exists.
Below is a reproducer for the commands, might needs to run a few times
until it triggers the race condition, I am not sure if there are more
commands in coreutils which are affected by this.
Thanks,
Paul
---
#!/usr/bin/env bash
set -e
TESTCOMMAND="chown -R $(id -u)"
# TESTCOMMAND="chgrp -R $(id -g)"
# TESTCOMMAND="chmod -R 0700"
# TESTCOMMAND="chcon -R -t user_tmp_t"
# TESTCOMMAND="ls -l -R"
TESTDIR=$(mktemp -d)
trap "rm -rf $TESTDIR" EXIT
mkdir -p $TESTDIR/t{0,1,2,3,4,5,6,7,8,9}
# seed many test files to make the race much more likely
for path in $TESTDIR/t{0..9}; do
for i in {0..255}; do
touch $path/$i
done
done
# start command in background so we can start the rm in parallel
$TESTCOMMAND $TESTDIR >/dev/null &
test_pid=$!
for path in $TESTDIR/t{0..9}; do
rm -rf $path &
done
wait "$test_pid"
wait