Hi/2. Bruno Haible wrote: > On native Windows, I see a test failure: > > FAIL: test-fdopendir > ==================== > > ../../gltests/test-fdopendir.c:76: assertion 'dup2 (fd, fd) == -1' failed > FAIL test-fdopendir.exe (exit status: 3) > > The cause of the problem is that POSIX [1] says: > "Upon calling closedir() the file descriptor shall be closed." > > That is, the fdopendir() call has to associate the argument fd with the > DIR object in such a way that fd gets closed when closedir() gets called > on the DIR object, but no earlier! — see the example in [1]: > closedir(d); // note this implicitly closes dfd > > So far, on mingw and MSVC, the DIR types (provided by mingw and gnulib, > respectively) don't contain a field for the file descriptor. For > implementing > opendir > readdir > rewinddir > closedir > this was sufficient. dirfd() always returned -1 in such an implementation. > But for fdopendir() it is not sufficient. > > It's not only a test failure; it's also a file descriptor leak: For > every pair of fdopendir/closedir calls, a file descriptor gets allocated > and not closed. > > This patch fixes it, by adding a 'fd_to_close' member. > > For kLIBC, KO Myung-Hun had added a similar mechanism, by keeping a list > of assocations between DIR objects and file descriptors. I believe > overriding the DIR type is the more efficient way to handle this, but > I have left the kLIBC code as it is. They can adapt the kLIBC code to > be like the mingw code, if they like to. > > [1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/fdopendir.html >
[...] > diff --git a/lib/dirfd.c b/lib/dirfd.c > index b2b1d25cdb..75b2163c35 100644 > --- a/lib/dirfd.c > +++ b/lib/dirfd.c > @@ -22,6 +22,10 @@ > #include <dirent.h> > #include <errno.h> > > +#if GNULIB_defined_DIR > +# include "dirent-private.h" > +#endif > + > #ifdef __KLIBC__ > # include <stdlib.h> > # include <io.h> > @@ -78,11 +82,17 @@ _gl_unregister_dirp_fd (int fd) > int > dirfd (DIR *dir_p) > { > +#if GNULIB_defined_DIR > + int fd = dir_p->fd_to_close; dirfd() allows to take an invalid `dir_p' ? > + if (fd == -1) > + errno = EINVAL; > + return fd; > +#else > int fd = DIR_TO_FD (dir_p); > if (fd == -1) > -#ifndef __KLIBC__ > +# ifndef __KLIBC__ > errno = ENOTSUP; > -#else > +# else > { > struct dirp_fd_list *dirp_fd; > > @@ -92,7 +102,8 @@ dirfd (DIR *dir_p) > > errno = EINVAL; > } > -#endif > +# endif > > return fd; > +#endif > } [...] -- KO Myung-Hun Using Mozilla SeaMonkey 2.7.2 Under OS/2 Warp 4 for Korean with FixPak #15 In VirtualBox v6.1.42 on Intel Core i7-3615QM 2.30GHz with 12GB RAM Korean OS/2 User Community : http://www.os2.kr/