Hi!

On Tue, Aug 19, 2025 at 12:48:36PM +0200, Bruno Haible wrote:
> > > Also, since the problem occurs only in a particular situation (/proc file
> > > system and FTS_TIGHT_CYCLE_CHECK), can you please submit a unit test as 
> > > well?
> > > Ideally, as a new file tests/test-fts-2.c.
> >
> > Making test for this is not simple, see the strace:
> >
> > 1: newfstatat(AT_FDCWD, "/proc/self/fd", {st_mode=S_IFDIR|0500,
> > st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
> > 2: write(1, " entering: /proc/self/fd\n", 26) = 26
> > 3: write(1, "Read: fd", 8)                 = 8
> > 4: openat(AT_FDCWD, "/proc/self/fd",
> > O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 3
> > 5: newfstatat(3, "", {st_mode=S_IFDIR|0500, st_size=0, ...}, AT_EMPTY_PATH) 
> > = 0
> > 6: fcntl(3, F_GETFL)                       = 0x38800 (flags
> > O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_NOFOLLOW|O_DIRECTORY)
> > 7: fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
> > 8: newfstatat(3, "", {st_mode=S_IFDIR|0500, st_size=0, ...}, AT_EMPTY_PATH) 
> > = 0
> >
> > On line 1 the directory is stat() the first time and it's inserted to
> > the hash immediately after printing the debug message on line 2.
> > Then fts_read() returns and one can process the FTSENT in his loop.
> > When fts_read() is entered again, libc opendir() gets called, which
> > makes syscalls 4 to 7. Failure of these is propagated by libc and is
> > correctly handled by the gnulib. Then on the line 8 the problematic stat
> > is called, which failure was not handled correctly.
>
> I see. And the fstat() of line 8, that duplicates the one of line 1, is needed
> because an arbitrary amount of time may elapse between lines 2 and 4, right?

I think the main problem is the file, on which stat has been called on
line 1, may be a completelly different file than the one opened on line 4,
thus it has to update the info.


> > Let me know if I should try to make the test by overriding glibc fstat
> > function of if it's too hackish.
>
> If it requires overriding fstat(), then let's override fstat(). The way to do
> so is to include <dlfcn.h> and use dlsym (RTLD_NEXT, "fstat") and
> dlsym (RTLD_NEXT, "fstat64").
>
> It's OK to make this unit test conditional on __GLIBC__ >= 2, in order to
> avoid trouble with non-ELF platforms like macOS or AIX.
>
> I think it's worth the effort. We do have strange / unportable unit tests in
> some cases (see e.g. test-free.c, test-memchr.c, test-memset_explicit.c).

Luckilly, it doesn't have to be that complicated as the first stat call
done by fts_read() is fstatat(), so I do not need to write any special
code to make the first call work. The only problem is I can't test it on
anything else than glibc and Linux and I'm not sure if this hack is
portable, so I limited it to __GLIBC__ as you suggested.

I will send updated patch.
BR,
  Petr

Reply via email to