-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 According to Bruno Haible on 5/24/2007 6:12 PM: > Hi Eric, > > I still don't see a proof that lseek is incorrect on mingw.
I tested by writing test-lseek.c first, and using echo hi | test-lseek && echo failed then repeating that test with the benefit of the lseek module, and seeing the difference in output on mingw. If test-lseek succeeds when stdin is a pipe, then it is an indication of a bug in lseek. > >> +# define lseek(f,o,w) \ >> + (GL_LINK_WARNING ("lseek does not fail with ESPIPE on non-seekable " \ >> + "files on some systems - " \ >> + "use gnulib module lseek for portability"), \ > > You expect that lseek fails on all non-seekable files? I agree that my wording is over-broad, but do you have any better wording? Maybe s/non-seekable files/pipes/. > > "The behavior of lseek() on devices which are incapable of seeking > is implementation-defined." We just defined it - we use the OS's definition if it was good enough, and if not, we correct it by saying all non-regular files (pipes, fifos, sockets, and then some) fail with ESPIPE. > But have you verified with fstat() that stdin is really a pipe, FIFO, or > socket? It could be larger than that set, but yes, the lseek module will correctly handle pipes, FIFOs, and sockets, and the only other POSIX types with defined behavior that we must worry about are regular files and directories. > >> + AC_CACHE_CHECK([whether lseek detects pipes], [gl_cv_func_lseek_pipe], >> + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <unistd.h>], >> +[#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ >> + Choke me. >> +#endif])], >> + [gl_cv_func_lseek_pipe=yes], [gl_cv_func_lseek_pipe=no])]) > > It should be possible to write a real test. How? Mingw doesn't provide pipe(), socket() is a bear to get right in a configure test, and I don't know how to coerce autoconf into guaranteeing that conftest's stdin is either a file or a pipe. > >> * tests/test-lseek.c: New file. > > It would be better if it would also test errno. OK, I'll see about updating it to do that. > > You said that you got an fflush failure on mingw. Could you please > show a test program that failed before? The m4 test suite detected failures on mingw due to this code that got invoked prior to the syscmd macro, in an attempt to follow the POSIX rule that for seekable streams, child processes should see the stream at the next character left unprocessed by the parent: if (lseek (STDIN_FILENO, 0, SEEK_CUR) >= 0 && fflush (stdin) == 0) { fseeko (stdin, 0, SEEK_CUR); } The failures in the m4 testsuite were due to lost data since the fflush discarded what was on the pipe, even though the fflush should never have been reached. > Adding such a test program to > the testsuite for 'fflush' would IMO have been the first thing to do. > Then, with the test case, we can hopefully determine whether the problem > is mingw's lseek or in gnulib's fflush. fflush on input pipes is intentionally undefined by POSIX, so I don't know how to add it to the testsuite. The gnulib implementation wants to be a no-op on pipes (ie. the first thing rpl_fflush looks for is whether stdin is even seekable, via ftello, before doing anything else to input streams); but on mingw, because the ftello lied, gnulib went on to call fflush, and the mingw fflush implementation discards unread data on the pipe. The bug, then, is not so much that the use of fflush lost data, but that the use of lseek was followed by fflush. Note that now, even without guarding the call to gnulib's fflush with lseek, that gnulib's fflush(input-pipe) is now a no-op on mingw as was the goal of the gnulib fflush implementation, since the ftello now catches that fact. But that does not necessarily hold for all implementations of fflush that comply to POSIX, so a portable program must still ensure it does not call fflush on a non-seekable input stream if it wants predictable behavior. > > I claim that there is also and still a bug in gnulib's fflush: POSIX > guarantees an ESPIPE failure only for pipes, FIFOs and sockets. But there > are other types of devices (COM:, NUL: etc.), on which lseek's behaviour > is unspecified. And you got evidence that when lseek behaves in unexpected > ways, gnulib's fflush will lose data. This is not a bug in gnulib, so much as an area of undefined behavior - it is up to the user to not call fflush (gnulib's or otherwise) if they know that the file is not in output mode and is not seekable. - -- Don't work too hard, make some time for fun as well! Eric Blake [EMAIL PROTECTED] -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (Cygwin) Comment: Public key at home.comcast.net/~ericblake/eblake.gpg Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGVj1184KuGfSFAYARAiJyAJ0c33ZDf1HYNuPFaw8OKtDNE2qZQwCePqlG DVbm41THuY442dWpqcFyCfM= =h8TR -----END PGP SIGNATURE-----