mirror of
https://https.git.savannah.gnu.org/git/findutils.git
synced 2026-01-27 01:44:23 +00:00
find: ignore more vanished subdirectories with -ignore_readdir_race
Similar to commit 889d001ab750 which handles vanished files better,
also fix the race for subdirectories (FTS_DNR).
Reproducer:
In average, the following produced 6-10 failures out of 1000 runs:
$ mkdir testdir
$ while :; do mkdir testdir/foo; rmdir testdir/foo; done &
$ for f in $(seq 1000); do \
find testdir -ignore_readdir_race -ls ; done >/dev/null
find: 'testdir/foo': No such file or directory
find: 'testdir/foo': No such file or directory
* find/ftsfind.c (consider_visiting): Return when FTS returned ENOENT
for FTS_DNR, i.e., unreadable directory, with -ignore_readdir_race.
* tests/find/readdir_race.sh: Add test.
* tests/local.mk (sh_tests): Reference it.
* NEWS (Bug Fixes): Amend and improve description of the previous fix.
See also https://savannah.gnu.org/bugs/?45930
This commit is contained in:
parent
eac8aecaad
commit
aff4e48c11
5
NEWS
5
NEWS
@ -4,8 +4,9 @@ GNU findutils NEWS - User visible changes. -*- outline -*- (allout)
|
||||
|
||||
** Bug Fixes
|
||||
|
||||
'find -ignore_readdir_race' now has a race between FTS read and the visiting
|
||||
of the entry when the file was removed. [#45930]
|
||||
'find -ignore_readdir_race' now better handles races between FTS reading a
|
||||
directory and visiting its entries when the file or directory was meanwhile
|
||||
removed. [#45930]
|
||||
|
||||
To fix a POSIX compatibility bug, -exec foo Z{} + is no longer a
|
||||
complete predicate, because '+' is only a terminator when it follows
|
||||
|
||||
@ -304,6 +304,9 @@ consider_visiting (FTS *p, FTSENT *ent)
|
||||
}
|
||||
if (ent->fts_info == FTS_DNR)
|
||||
{
|
||||
/* Ignore ENOENT error for vanished directories. */
|
||||
if (ENOENT == ent->fts_errno && options.ignore_readdir_race)
|
||||
return;
|
||||
nonfatal_target_file_error (ent->fts_errno, ent->fts_path);
|
||||
if (options.do_dir_first)
|
||||
{
|
||||
@ -355,7 +358,7 @@ consider_visiting (FTS *p, FTSENT *ent)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Ignore unlink() error for vanished files. */
|
||||
/* Ignore ENOENT error for vanished files. */
|
||||
if (ENOENT == ent->fts_errno && options.ignore_readdir_race)
|
||||
return;
|
||||
|
||||
|
||||
48
tests/find/readdir_race.sh
Executable file
48
tests/find/readdir_race.sh
Executable file
@ -0,0 +1,48 @@
|
||||
#!/bin/sh
|
||||
# Verify that -ignore_readdir_race properly handles vanished files/directories.
|
||||
|
||||
# Copyright (C) 2024 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"; fu_path_prepend_
|
||||
print_ver_ find
|
||||
|
||||
# Require seq(1) for this test - which may not be available
|
||||
# on some systems, e.g on some *BSDs.
|
||||
seq 2 >/dev/null 2>&1 \
|
||||
|| skip_ "required utility 'seq' missing"
|
||||
|
||||
mkdir testdir || framework_failure_
|
||||
|
||||
# Constantly create and remove a subdirectory in the background.
|
||||
# Disable shell debugging for this part.
|
||||
# Terminate the background process later again.
|
||||
endless_mkdir_rmdir() {
|
||||
{ set +x; } 2>/dev/null
|
||||
while :; do mkdir testdir/foo; rmdir testdir/foo; done
|
||||
}
|
||||
endless_mkdir_rmdir & pid=$!
|
||||
cleanup_() { kill $pid 2>/dev/null && wait $pid; }
|
||||
|
||||
# Now run find(1) many times.
|
||||
> err
|
||||
for f in $(seq 1000); do \
|
||||
find testdir -ignore_readdir_race -ls 2>> err || fail=1; \
|
||||
done > out
|
||||
|
||||
test 1000 -le $( wc -l < out ) || fail=1
|
||||
compare /dev/null err || fail=1
|
||||
|
||||
Exit $fail
|
||||
@ -131,6 +131,7 @@ sh_tests = \
|
||||
tests/find/newer.sh \
|
||||
tests/find/opt-numeric-arg.sh \
|
||||
tests/find/sv-bug-66365-exec.sh \
|
||||
tests/find/readdir_race.sh \
|
||||
tests/find/user-group-max.sh \
|
||||
tests/xargs/conflicting_opts.sh \
|
||||
tests/xargs/verbose-quote.sh \
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user