This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
Hi, following a discussion on the Cygwin mailing list(*), I applied the below patch. It introduces a new macro, _STDIO_BSD_SEMANTICS, with the following property: In 2006, a patch has been introduced in newlib, which changed the semantics of the fclose and exit calls. BSD semantics, as followed by all BSD systems, Glibc, and by newlib up to 2006, are so that on fclose and exit, FILE streams are flushed (and thus the underlying file descriptor seeked!) only if the stream has been written to. POSIX semantics, as followed by Solaris and newlib since 2006, are so that on fclose and exit, FILE streams are flushed (and thus seeked) unconditionally, even for read-only streams. This subtil difference has interesting side-effects, as soon as processes have forked or spawned child processes which inherited a stream read by the parent. Consider these two scenarios as examples: Input file foo.txt: aaaaaaa bbbbbbb ccccccc Example 1 (pseudo code): fp = fopen ("foo.txt", "r"); while (fgets (buf, fp)) { fprintf (stderr, "%s %ld\n", buf, lseek(fileno(fp), 0, SEEK_CUR)); switch (fork ()) { case CHILD: exit (0); case PARENT: wait (); break; } } Output under BSD sematics: aaaaaaa 24 bbbbbbb 24 ccccccc 24 Output under POSIX semantics: aaaaaaa 24 bbbbbbb 8 ccccccc 0 aaaaaaa 24 bbbbbbb 8 ccccccc 0 aaaaaaa 24 bbbbbbb 8 ccccccc 0 [...ad infinitum...] Example 2: sh$ { sed -n 1q; sed -n 1q; cat; } < foo.txt Output under BSD semantics: <nothing> Output under POSIX semantics: ccccccc So my patch now introduces the _STDIO_BSD_SEMANTICS flag. If you define it for your target (for instance, in sys/config.h), you get BSD semantics, while, as long as _STDIO_BSD_SEMANTICS is undefined, your target sticks to POSIX semantics. Corinna (*) http://cygwin.com/ml/cygwin/2014-01/threads.html#00110 Introduce _STDIO_BSD_SEMANTICS flag to switch fclose/exit file flushing semantics from POSIX to BSD. * libc/stdio/fclose.c (_fclose_r): Conditionalize file flushing on _STDIO_BSD_SEMANTICS. Call __sflush_r rather than _fflush_r. Add comment. * libc/stdio/fflush.c (__sflushw_r): New function, only available if _STDIO_BSD_SEMANTICS is defined. * libc/stdio/findfp.c (_cleanup_r): Call _fwalk_reent rather than _fwalk. Conditionalize cleanup function call on _STDIO_BSD_SEMANTICS. Add comments. Add FIXME. * libc/stdio/local.h (__sflushw_r): Declare if _STDIO_BSD_SEMANTICS is defined. Index: libc/stdio/fclose.c =================================================================== RCS file: /cvs/src/src/newlib/libc/stdio/fclose.c,v retrieving revision 1.18 diff -u -p -r1.18 fclose.c --- libc/stdio/fclose.c 26 Mar 2013 16:07:55 -0000 1.18 +++ libc/stdio/fclose.c 17 Jan 2014 10:50:18 -0000 @@ -92,10 +92,15 @@ _DEFUN(_fclose_r, (rptr, fp), #endif return (0); } - /* Unconditionally flush to allow special handling for seekable read - files to reposition file to last byte processed as opposed to - last byte read ahead into the buffer. */ - r = _fflush_r (rptr, fp); +#ifdef _STDIO_BSD_SEMANTICS + /* BSD and Glibc systems only flush streams which have been written to. */ + r = (fp->_flags & __SWR) ? __sflush_r (rptr, fp) : 0; +#else + /* Follow POSIX semantics exactly. Unconditionally flush to allow + special handling for seekable read files to reposition file to last + byte processed as opposed to last byte read ahead into the buffer. */ + r = __sflush_r (rptr, fp); +#endif if (fp->_close != NULL && fp->_close (rptr, fp->_cookie) < 0) r = EOF; if (fp->_flags & __SMBF) Index: libc/stdio/fflush.c =================================================================== RCS file: /cvs/src/src/newlib/libc/stdio/fflush.c,v retrieving revision 1.19 diff -u -p -r1.19 fflush.c --- libc/stdio/fflush.c 23 Oct 2013 10:04:43 -0000 1.19 +++ libc/stdio/fflush.c 17 Jan 2014 10:50:18 -0000 @@ -204,6 +204,19 @@ _DEFUN(__sflush_r, (ptr, fp), return 0; } +#ifdef _STDIO_BSD_SEMANTICS +/* Called from _cleanup_r. At exit time, we don't need file locking, + and we don't want to move the underlying file pointer unless we're + writing. */ +int +_DEFUN(__sflushw_r, (ptr, fp), + struct _reent *ptr _AND + register FILE *fp) +{ + return (fp->_flags & __SWR) ? __sflush_r (ptr, fp) : 0; +} +#endif + int _DEFUN(_fflush_r, (ptr, fp), struct _reent *ptr _AND Index: libc/stdio/findfp.c =================================================================== RCS file: /cvs/src/src/newlib/libc/stdio/findfp.c,v retrieving revision 1.26 diff -u -p -r1.26 findfp.c --- libc/stdio/findfp.c 25 Apr 2013 15:29:19 -0000 1.26 +++ libc/stdio/findfp.c 17 Jan 2014 10:50:18 -0000 @@ -170,8 +170,17 @@ _VOID _DEFUN(_cleanup_r, (ptr), struct _reent *ptr) { - _CAST_VOID _fwalk(ptr, fclose); - /* _CAST_VOID _fwalk (ptr, fflush); */ /* `cheating' */ +#ifdef _STDIO_BSD_SEMANTICS + /* BSD and Glibc systems only flush streams which have been written to + at exit time. Calling flush rather than close for speed, as on + the aforementioned systems. */ + _CAST_VOID _fwalk_reent (ptr, __sflushw_r); +#else + /* Otherwise close files and flush read streams, too. + FIXME: Do we really have to call fclose rather than fflush for + RTOS compatibility? */ + _CAST_VOID _fwalk_reent (ptr, _fclose_r); +#endif } #ifndef _REENT_ONLY Index: libc/stdio/local.h =================================================================== RCS file: /cvs/src/src/newlib/libc/stdio/local.h,v retrieving revision 1.38 diff -u -p -r1.38 local.h --- libc/stdio/local.h 23 Oct 2013 10:04:43 -0000 1.38 +++ libc/stdio/local.h 17 Jan 2014 10:50:18 -0000 @@ -147,6 +147,9 @@ int _EXFUN(_svfiwprintf_r,(struct extern FILE *_EXFUN(__sfp,(struct _reent *)); extern int _EXFUN(__sflags,(struct _reent *,_CONST char*, int*)); extern int _EXFUN(__sflush_r,(struct _reent *,FILE *)); +#ifdef _STDIO_BSD_SEMANTICS +extern int _EXFUN(__sflushw_r,(struct _reent *,FILE *)); +#endif extern int _EXFUN(__srefill_r,(struct _reent *,FILE *)); extern _READ_WRITE_RETURN_TYPE _EXFUN(__sread,(struct _reent *, void *, char *, _READ_WRITE_BUFSIZE_TYPE)); -- Corinna Vinschen Cygwin Maintainer Red Hat
Attachment:
pgpMC2_0SUxsG.pgp
Description: PGP signature
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |