[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: 'fflush' test failure on Cygwin
From: |
Bruno Haible |
Subject: |
Re: 'fflush' test failure on Cygwin |
Date: |
Fri, 13 Apr 2007 03:30:13 +0200 |
User-agent: |
KMail/1.5.4 |
Eric Blake wrote:
> > File offset is wrong.
> > FAIL: test-fflush.exe
> >
> > In test-fflush.c line 70, the return value from lseek() is 10 instead of the
> > expected 5.
>
> That is due to a bug in newlib's fflush that I fixed on 2006-12-14.
>
> I personally don't use a cygwin that old, nor do I recommend it to others
But it's the goal of the 'fflush' module to make this test work, no?
> But seeing as how the failure symptom is the same as that of MacOSX,
Indeed, on MacOS X 10.3.9, the lseek call in test-fflush.c:70 also yields 10,
not 5.
> I'm wondering if anyone has better ideas of how to force stdio to reposition
> the offset of the underlying fd when fflush (or fpurge) followed by fseek
> is not powerful enough to do the same. I could always do a raw lseek
> myself, but that makes me worry that if stdio has read in a buffer, then
> stdio will be confused because the fd changed behind its back.
After looking at the MacOS X source files
Libc-320.1.3/stdio/FreBSD/fflush.c
Libc-320.1.3/stdio/FreBSD/fseek.c
(from http://developer.apple.com/opensource/ -> Darwin -> MacOS X 10.3.9
Source -> Libc-320.1.3) for two hours, here's what I think:
1) fpurge exists on MacOS X, but only clears the buffer, without changing
the file descriptor's position in the kernel. So it needs this change
(otherwise the stream's position before the fflush() call is lost):
*** lib/fflush.c 2007-04-13 00:15:11.000000000 +0200
--- lib/fflush.c 2007-04-13 02:44:10.000000000 +0200
***************
*** 57,63 ****
/* To get here, we must be flushing a seekable input stream, so the
semantics of fpurge are now appropriate. */
#if HAVE_FPURGE
! result = fpurge (stream);
#elif HAVE___FPURGE
/* __fpurge has no return value, and on Solaris, we can't even trust
errno. So assume it succeeds. */
--- 57,72 ----
/* To get here, we must be flushing a seekable input stream, so the
semantics of fpurge are now appropriate. */
#if HAVE_FPURGE
! {
! off_t pos = ftello (stream);
!
! result = fpurge (stream);
! if (result == 0)
! {
! if (lseek (fileno (stream), pos, SEEK_SET) == -1)
! result = EOF;
! }
! }
#elif HAVE___FPURGE
/* __fpurge has no return value, and on Solaris, we can't even trust
errno. So assume it succeeds. */
2) fseek() is heavily optimized: fseeko (fp, pos, SEEK_SET) will position
the file descriptor to pos & ~fp->_blksize and then read one buffer,
[or if pos is inside the current buffer, optimize even more: just
change some pointers and counters, without accessing the file descriptor],
unless
- fp is not seekable, or
- fp is open for writing (__SWR | __SRW), or
- fp is unbuffered (__SNBF), or
- fp has an unusual block size set through setvbuf (__SNPT).
If your fflush or fseek was to invoke setvbuf, it's hard to keep programs
working that use setvbuf as well.
A solution might be to make a wrapper around fseek() roughly like this:
rpl_fseek (...)
{
if (fp is not open for writing
&& fp's buffer is empty, like after fpurge)
perform just an lseek
else
fseek (...);
}
The primitives for "fp is not open for writing" can be written in the
same spirit as the 'fseterr' and 'fpending' modules.
Bruno
- 'fflush' test failure on Cygwin, Bruno Haible, 2007/04/12
- Re: 'fflush' test failure on Cygwin, Eric Blake, 2007/04/12
- Re: 'fflush' test failure on Cygwin,
Bruno Haible <=
- Re: operations on FILE streams, Bruno Haible, 2007/04/13
- Re: operations on FILE streams, Paul Eggert, 2007/04/13
- Re: operations on FILE streams, Bruno Haible, 2007/04/13
- Re: operations on FILE streams, Eric Blake-1, 2007/04/13
- Re: operations on FILE streams, Bruno Haible, 2007/04/13
- Re: operations on FILE streams, Paul Eggert, 2007/04/13