bugfindutils - Bugs: bug #45930, -ignore_readdir_race ineffective...

 
 

bug #45930: -ignore_readdir_race ineffective in find 4.5.11 and 4.5.14

Submitter:  None
Submitted:  Fri 11 Sep 2015 01:05:25 PM UTC
Votes: 10
 
Category:  find Severity:  3 - Normal
Item Group:  None Status:  Fixed
Privacy:  Public Assigned to:  berny
Originator Name:  Rainer Canavan Originator Email:  -email is unavailable-
Open/Closed:  Open Release:  4.5.14
Fixed Release:  4.11.0
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Wed 29 Jan 2025 08:58:08 PM UTC, comment #18: 

This issue is not because of the directory type, but ...ugh,
rather because the -execdir action resets ignore_readdir_race=false:

https://git.savannah.gnu.org/cgit/findutils.git/tree/find/parser.c?id=faa13013686b17#n2812

You can verify by adding another -ignore_readdir_race at the very
end of the command line (which will issue a warning about that
but will still ignore the ENOENT errors:


$ ~/findutils/find/find test -ignore_readdir_race -name 'bin' -execdir rmdir 'foo' 'bar' 'baz' ';' -ignore_readdir_race || echo 'errors'
find/find: warning: you have specified the global option -ignore_readdir_race after the argument -name, but global options are not positional, i.e., -ignore_readdir_race affects tests specified before it as well as those specified after it.  Please specify global options before other arguments.


This change for -execdir has been added in 2005 in this commit:
https://git.savannah.gnu.org/cgit/findutils.git/commit/?id=74a750b11fba8

@James: do you remember or have email notes about why -execdir should disable -ignore_readdir_race?

Bernhard Voelker <berny>
Group administrator
Wed 29 Jan 2025 01:45:05 AM UTC, comment #17: 

Works with files but not directories as of master faa13013686b179ab8f23a9ea7d238fb090c5ffe

Test case:

$ mkdir --parents 'test/foo' 'test/bar' 'test/bin' 'test/baz'
$ ./findutils/find/find 'test' -ignore_readdir_race -name 'bin' -execdir rmdir 'foo' 'bar' 'baz' ';' || echo 'errors'
./findutils/find/find: ‘test/foo’: No such file or directory
./findutils/find/find: ‘test/baz’: No such file or directory
errors


I'm using find to locate source trees for cleaning, but the spurious errors confuse my backup script.

Anonymous
Mon 23 Dec 2024 12:10:21 PM UTC, comment #16: 

Thanks for confirmation.
Pushed along with a test at:
  https://git.sv.gnu.org/cgit/findutils.git/commit/?id=aff4e48c11929

> BTW, is a find starting-point really allowed to be a regular file instead of a directory?


yes, "everything is a file" :-)
This feature is quite helpful, e.g. if you want to check whether a file
has been modified in the last N days:

$ find /etc/passwd -mtime -100 -exec ls -logd '{}' +
$ find /etc/passwd -mtime -365 -exec ls -logd '{}' +
-rw-r--r-- 1 3646 Jun  4  2024 /etc/passwd


Bernhard Voelker <berny>
Group administrator
Wed 18 Dec 2024 12:00:37 AM UTC, comment #15: 

comment #14:

> Are you sure?
> Exactly your test case is now really stable with the patch from comment #11 here.


Thanks for double-checking!

When I edited the command-line to run the executable containing the fix, I did:

$ while :; do find ~/downloads/findutils/find/find findtest -ignore_readdir_race; done >/dev/null

It took me a while to spot the careless error.  :-(

When I actually run the correct executable I see my debug message instead of ENOENT, so the fix is good.

Sorry for getting it wrong and wasting an iteration!

BTW, is a find starting-point really allowed to be a regular file instead of a directory?

Martin Schwenke <martins>
Tue 17 Dec 2024 11:37:33 PM UTC, comment #14: 

Are you sure?
Exactly your test case is now really stable with the patch from comment #11 here.

Bernhard Voelker <berny>
Group administrator
Tue 17 Dec 2024 11:07:59 PM UTC, comment #13: 

comment #11:

> Alright, that's yet another case than the already-fixed one.
> The fix for this one would look like the following.


> diff --git a/find/ftsfind.c b/find/ftsfind.c
> index 89ed9dd0..f57fa809 100644
> --- a/find/ftsfind.c
> +++ b/find/ftsfind.c
> @@ -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)
>          {


> WDYT?


I just tested that change with the scenario in my previous comment and I still see the issue.  I added some debug output (to stderr) before the new early return but the debug output is never printed.  :-(

I had hoped to understand this and submit a patch myself, but understanding FTS is difficult...

Martin Schwenke <martins>
Tue 17 Dec 2024 10:57:08 PM UTC, comment #12: 

comment #10:

> > gnulib/lib/ftc.c (FTC)
>
> Do you mean FTS?


Yes, oops!  Brain overload.  :-(

> > This means that when find recurses into a subdirectory, it complains when that subdirectory doesn't exist.
>
> Ah, you mean something like this:
>


> $ mkdir -p foo
> $ find -ignore_readdir_race -name . -o -name foo -print -exec rmdir {} \; -o -prune
> ./foo
> find: ‘./foo’: No such file or directory


>
> Actually this is fixable in ftsfind.c.  ignore_readdir_race is already handled for FTS_NS, it just has to be added to FTS_DNR as well.


I actually mean the case where something else is independently updating the directory, creating and removing subdirectories.  This is similar to the /proc case but can be recreated with:

$ while :; do mkdir findtest/foo; rmdir findtest/foo; done &
[1] 776
$ while :; do find findtest -ignore_readdir_race; done >/dev/null
find: ‘findtest/foo’: No such file or directory
find: ‘findtest/foo’: No such file or directory
find: ‘findtest/foo’: No such file or directory
find: ‘findtest/foo’: No such file or directory
find: ‘findtest/foo’: No such file or directory
find: ‘findtest/foo’: No such file or directory
^C
$ kill %1
[1]+  Terminated              while :; do
    mkdir findtest/foo; rmdir findtest/foo;
done


Martin Schwenke <martins>
Tue 17 Dec 2024 10:14:11 PM UTC, comment #11: 

Alright, that's yet another case than the already-fixed one.
The fix for this one would look like the following.

diff --git a/find/ftsfind.c b/find/ftsfind.c
index 89ed9dd0..f57fa809 100644
--- a/find/ftsfind.c
+++ b/find/ftsfind.c
@@ -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)
         {

WDYT?

Bernhard Voelker <berny>
Group administrator
Tue 17 Dec 2024 06:03:08 PM UTC, comment #10: 


> gnulib/lib/ftc.c (FTC)


Do you mean FTS?

> This means that when find recurses into a subdirectory, it complains when that subdirectory doesn't exist.


Ah, you mean something like this:


$ mkdir -p foo
$ find -ignore_readdir_race -name . -o -name foo -print -exec rmdir {} \; -o -prune
./foo
find: ‘./foo’: No such file or directory


Actually this is fixable in ftsfind.c.  ignore_readdir_race is already handled for FTS_NS, it just has to be added to FTS_DNR as well.

Tavian Barnes <tavianator>
Mon 16 Dec 2024 12:04:53 AM UTC, comment #9: 

The problem seems to be simple fairly simple (but not necessarily simple to solve):

gnulib/lib/ftc.c (FTC) seems to have no support for ignoring the readdir race (-ignore_readdir_race).

This means that when find recurses into a subdirectory, it complains when that subdirectory doesn't exist.

So, there are 2 choices:

  • Plumb an option all the way through FTC to support ignoring the readdir race
  • Drop (or ignore) -ignore_readdir_race completely and ignore the race unconditionally, everywhere.  After all, this is "find", not "not found". ;-)  I doubt anyone cares about things that aren't found.  If they were in a directory, but don't seem to be there anymore, then they are gone... not found!
Martin Schwenke <martins>
Tue 17 Sep 2024 08:53:13 PM UTC, comment #8: 

Pushed with a fix for a minor typo in NEWS at:
https://git.sv.gnu.org/cgit/findutils.git/commit/?id=889d001ab75

Bernhard Voelker <berny>
Group administrator
Mon 16 Sep 2024 10:13:18 PM UTC, comment #7: 

I propose to push the attached, as this make the race already
much more unlikely.  This is included in downstream Redhat and
Fedora since a while.

(file #56434)

Bernhard Voelker <berny>
Group administrator
Wed 04 Sep 2019 08:42:12 PM UTC, comment #6: 

No, it's not fixed.  I've identified at least one place where catching ENOENT helps ...


diff --git a/find/ftsfind.c b/find/ftsfind.c
index 0d96c4ca..6aeac28c 100644
--- a/find/ftsfind.c
+++ b/find/ftsfind.c
@@ -401,6 +401,10 @@ consider_visiting (FTS *p, FTSENT *ent)
            }
          else
            {
+             /* Ignore unlink() error for vanished files.  */
+             if (ENOENT == ent->fts_errno && options.ignore_readdir_race)
+                 return;
+
              nonfatal_target_file_error (ent->fts_errno, ent->fts_path);
              /* Continue despite the error, as file name without stat info
               * might be better than not even processing the file name. This


..., but there seem to be more.
Here, the reproducer in #4 still "works".

Bernhard Voelker <berny>
Group administrator
Sun 01 Sep 2019 08:58:38 AM UTC, comment #5: 

Trying the reproducer in #4 with Findutils 4.7.0, I see no problems.    Bernhard, did you fix this already?   If the problem is partially-fixed, is it fixed enough that we can close the bug?

James Youngman <jay>
Group administrator
Thu 13 Jun 2019 06:18:39 AM UTC, comment #4: 

The issue can be triggered with a shorter command line.

Run this in one terminal:

while env true; do sleep .001; done

and in another one this find(1) command:

$ find /proc -ignore_readdir_race -maxdepth 3 > /dev/null


With that, find(1) is hitting the error pretty reliably.

FWIW: Interestingly, 'oldfind', i.e., the old non-FTS implementation even runs into an endless loop:

...
/home/berny/findutils/find/oldfind: ‘/proc/1143/net’: Invalid argument
/home/berny/findutils/find/oldfind: ‘/proc/1143/net’: Invalid argument
/home/berny/findutils/find/oldfind: ‘/proc/1143/net’: Invalid argument
/home/berny/findutils/find/oldfind: ‘/proc/1143/net’: Invalid a^C


Bernhard Voelker <berny>
Group administrator
Thu 06 Jun 2019 09:04:54 AM UTC, comment #3: 

Hello,

I can confirm "-ignore_readdir_race" not working:
- On CentOS-7 with find v4.5.11
- On OpenSuse with find v4.5.12

EXAMPLE:
root|dev-opensuse-server01|10:57|0|~: find /proc -ignore_readdir_race -maxdepth 3 -path "/proc/[0-9]*/fd/*" -type l \( -lname '/dev/shm/*' -prune -o -lname '*(deleted)' -printf '"%p (absent) (%Y)"\n' -o -printf '"%p (present) (%Y)"\n' \) > /dev/null; echo -e "RETVALUE: ${?}"
find: ‘/proc/4063’: No such file or directory
find: ‘/proc/4064’: No such file or directory
find: ‘/proc/4069’: No such file or directory
find: ‘/proc/4072’: No such file or directory
RETVALUE: 1

EXPECTED RESULT:
- No error about missing directories/files
- Return value of zero (0)

Either it is broken or I misunderstood the purpose of this feature...

Anonymous
Fri 18 Aug 2017 01:20:42 AM UTC, comment #2: 

I can confirm the issue with CentOS7. Package info: findutils-4.5.11-5.el7.x86_64

Have a CRON that runs on multiple machine at the same time. Part of the script remove old log file in a common NFS folder.
It uses 'find' for this and checks the file timestamp (mtime)

It's pretty much guaranteed to get into a race condition with  this specific setup (NFS mount..).

Using -ignore_readdir_race does not seem to have any effect.


Alex <arekkusu>
Fri 11 Sep 2015 01:17:57 PM UTC, comment #1: 

I haven't tried other filesystems or kernels, the ones used are xfs (rw,noatime,attr2,inode64,noquota) and linux 3.10.0-229.11.1.el7.x86_64

Rainer Canavan <canavan>
Fri 11 Sep 2015 01:05:25 PM UTC, original submission:  

We have a cron job that is used to clean cache directories. There's a log going on in that directory, especially files getting moved from temporary names to their final names after they have been written completely. We have noticed that the find that is supplied with Centos7 (version 4.5.11) as well as a find 4.5.14 built from unmodified source frequently prints "No such file or directory" errors for the initial filenames of the temporary files, despite the fact that we have specified -ignore_readdir_race, e.g.:

/usr/bin/find: ‘./engine/projects/portal/istmp1NYV9b’: No such file or directory

This does not happen with a find 4.4.2 compiled from source. A trivial find in the "busy" directory is sufficient to triffer the error message almost 100% of the time:

find . -ignore_readdir_race > /dev/null


Anonymous

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #56434:  0001-find-ignore-more-vanished-entries-with-ignore_readdi.patch added by berny (2KiB - text/x-patch - [PATCH] find: ignore more vanished entries with -ignore_readdir_race)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by tavianator (Posted a comment)
  • -email is unavailable- added by martins (Posted a comment)
  • -email is unavailable- added by jay (Posted a comment)
  • -email is unavailable- added by berny (Posted a comment)
  • -email is unavailable- added by arekkusu (Posted a comment)
  • -email is unavailable- added by arekkusu (Voted in favor of this item)
  • -email is unavailable- added by canavan (Posted a comment)
  • -email is unavailable- added by None (Submitted the item)
  •  

    There are 10 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only logged-in users can vote.

     

    Follow 6 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2024-09-17 berny StatusCode Review Fixed
    2024-09-16 berny Attached File- Added 0001-find-ignore-more-vanished-entries-with-ignore_readdi.patch, #56434
        StatusNone Code Review
        Fixed ReleaseNone 4.11.0
    2019-09-01 jay Assigned toNone berny
    2017-08-18 arekkusu Carbon-Copy- Added arekkusu

    Back to the top

    Powered by Savane 3.14-7003.
    Corresponding source code