find: make -delete honour the -ignore_readdir_race option

* find/pred.c (pred_delete): Return true when the -ignore_readdir_race
option is active and unlinkat() came back with ENOENT.
* doc/find.texi (Option -ignore_readdir_race): Document the change.
(Action -delete): Likewise.
* find/find.1: Likewise.
* NEWS (Bug Fixes): Mention the fix.

For now, it seems a bit hard to add a proper test for this,
so the following shell snippet demonstrates the race:

  $ seq 10 | xargs touch
  $ env time -f 'find exit status: %x\nfind time: %e' \
      find -ignore_readdir_race -type f \
        -delete \
        -exec sh -c 'sleep $(basename {})' \; \
        -printf 'find deleted: %p\n' \
        & \
    sleep 20; \
    seq 10 | xargs rm -fv; \
    wait $!

Reported by Alexander Golubev in
https://savannah.gnu.org/bugs/?52981
This commit is contained in:
2018-01-30 23:30:09 +01:00
parent 2d6ce760f1
commit 0afb2efada
4 changed files with 46 additions and 1 deletions

4
NEWS
View File

@@ -54,6 +54,10 @@ Some minor documentation improvements are listed in "Bug Fixes" below.
** Bug Fixes
#52981: find: the '-delete' action no longer complains about disappeared files
when the '-ignore_readdir_race' option is given, too. That action will
also returns true in such a case now.
#52220: 'find -D' without any further argument no longer crashes.
Bug present since the implementation of -D in FINDUTILS_4_3_1-1.

View File

@@ -1424,7 +1424,15 @@ gives a significant increase in search speed.
If a file disappears after its name has been read from a directory but
before @code{find} gets around to examining the file with @code{stat},
don't issue an error message. If you don't specify this option, an
error message will be issued. This option can be useful in system
error message will be issued.
Furthermore, @code{find} with the @samp{-ignore_readdir_race} option
will ignore errors of the @samp{-delete} action in the case the file
has disappeared since the parent directory was read: it will not output
an error diagnostic, and the return code of the @samp{-delete} action
will be true.
This option can be useful in system
scripts (cron scripts, for example) that examine areas of the
filesystem that change frequently (mail queues, temporary directories,
and so forth), because this scenario is common for those sorts of
@@ -2787,6 +2795,11 @@ explicitly.
If @samp{-delete} fails, @code{find}'s exit status will be nonzero
(when it eventually exits).
Together with the @samp{-ignore_readdir_race} option, @code{find} will
ignore errors of the @samp{-delete} action in the case the file has disappeared
since the parent directory was read: it will not output an error diagnostic, and
the return code of the @samp{-delete} action will be true.
@end deffn
@node Adding Tests

View File

@@ -495,6 +495,17 @@ this option on and part of it with this option off
(if you need to do that, you will need to issue two \fBfind\fR commands
instead, one with the option and one without it).
Furthermore,
.B find
with the
.B \-ignore_readdir_race
option will ignore errors of the
.B \-delete
action in the case the file has disappeared since the parent directory was read:
it will not output an error diagnostic, and the return code of the
.B \-delete
action will be true.
.IP "\-maxdepth \fIlevels\fR"
Descend at most \fIlevels\fR (a non-negative integer) levels of
directories below the starting-points.
@@ -1087,6 +1098,17 @@ and
.B \-delete
together.
Together with the
.B \-ignore_readdir_race
option,
.B find
will ignore errors of the
.B \-delete
action in the case the file has disappeared since the parent directory was
read: it will not output an error diagnostic, and the return code of the
.B \-delete
action will be true.
.IP "\-exec \fIcommand\fR ;"
Execute
.IR command ;

View File

@@ -316,6 +316,12 @@ pred_delete (const char *pathname, struct stat *stat_buf, struct predicate *pred
}
else
{
if (ENOENT == errno && options.ignore_readdir_race)
{
/* Ignore unlink() error for vanished files. */
errno = 0;
return true;
}
if (EISDIR == errno)
{
if ((flags & AT_REMOVEDIR) == 0)