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




Reply via email to