https://bugs.gentoo.org/370413 http://sourceware.org/bugzilla/show_bug.cgi?id=12724 https://bugzilla.novell.com/show_bug.cgi?id=711829 http://redmine.ruby-lang.org/issues/5108 This reverts the following patch from upstream PR 12724, which can cause surprising changes in fclose behaviour when multiple file handles refer to the same file (fclose on one changes file position on the other). See bnc #711829. git diff -R 'fcabc0f8b185f9e0a9289720be5ede6c39b3bf21^!' 2011-05-13 Ulrich Drepper [BZ #12724] * libio/fileops.c (_IO_new_file_close_it): Always flush when currently writing and seek to current position when not. * libio/Makefile (tests): Add bug-fclose1. * libio/bug-fclose1.c: New file. 2011-05-12 Ulrich Drepper [BZ #12511] diff --git b/libio/Makefile a/libio/Makefile index ec30904..83b9458 100644 --- b/libio/Makefile +++ a/libio/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1995-2004,2006-2009,2011 Free Software Foundation, Inc. +# Copyright (C) 1995-2004,2006,2007,2008,2009 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -58,7 +58,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ tst-memstream1 tst-memstream2 \ tst-wmemstream1 tst-wmemstream2 \ bug-memstream1 bug-wmemstream1 \ - tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos bug-fclose1 + tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos test-srcs = test-freopen all: # Make this the default target; it will be defined in Rules. diff --git b/libio/bug-fclose1.c a/libio/bug-fclose1.c deleted file mode 100644 index f1e09f5..0000000 --- b/libio/bug-fclose1.c +++ /dev/null @@ -1,132 +0,0 @@ -// BZ #12724 - -static void do_prepare (void); -#define PREPARE(argc, argv) do_prepare () -static int do_test (void); -#define TEST_FUNCTION do_test() -#include "../test-skeleton.c" - - -static int fd; - - -static void -do_prepare (void) -{ - fd = create_temp_file ("bug-fclose1.", NULL); - if (fd == -1) - { - printf ("cannot create temporary file: %m\n"); - exit (1); - } -} - - -static int -do_test (void) -{ - static const char pattern[] = "hello world"; - - /* Prepare a seekable file. */ - if (write (fd, pattern, sizeof pattern) != sizeof pattern) - { - printf ("cannot write pattern: %m\n"); - return 1; - } - if (lseek (fd, 1, SEEK_SET) != 1) - { - printf ("cannot seek after write: %m\n"); - return 1; - } - - /* Create an output stream visiting the file; when it is closed, all - other file descriptors visiting the file must see the new file - position. */ - int fd2 = dup (fd); - if (fd2 < 0) - { - printf ("cannot duplicate descriptor for writing: %m\n"); - return 1; - } - FILE *f = fdopen (fd2, "w"); - if (f == NULL) - { - printf ("first fdopen failed: %m\n"); - return 1; - } - if (fputc (pattern[1], f) != pattern[1]) - { - printf ("fputc failed: %m\n"); - return 1; - } - if (fclose (f) != 0) - { - printf ("first fclose failed: %m\n"); - return 1; - } - errno = 0; - if (lseek (fd2, 0, SEEK_CUR) != -1) - { - printf ("lseek after fclose after write did not fail\n"); - return 1; - } - if (errno != EBADF) - { - printf ("lseek after fclose after write did not fail with EBADF: %m\n"); - return 1; - } - off_t o = lseek (fd, 0, SEEK_CUR); - if (o != 2) - { - printf ("\ -lseek on original descriptor after first fclose returned %ld, expected 2\n", - (long int) o); - return 1; - } - - /* Likewise for an input stream. */ - fd2 = dup (fd); - if (fd2 < 0) - { - printf ("cannot duplicate descriptor for reading: %m\n"); - return 1; - } - f = fdopen (fd2, "r"); - if (f == NULL) - { - printf ("second fdopen failed: %m\n"); - return 1; - } - char c = fgetc (f); - if (c != pattern[2]) - { - printf ("getc returned %c, expected %c\n", c, pattern[2]); - return 1; - } - if (fclose (f) != 0) - { - printf ("second fclose failed: %m\n"); - return 1; - } - errno = 0; - if (lseek (fd2, 0, SEEK_CUR) != -1) - { - printf ("lseek after fclose after read did not fail\n"); - return 1; - } - if (errno != EBADF) - { - printf ("lseek after fclose after read did not fail with EBADF: %m\n"); - return 1; - } - o = lseek (fd, 0, SEEK_CUR); - if (o != 3) - { - printf ("\ -lseek on original descriptor after second fclose returned %ld, expected 3\n", - (long int) o); - return 1; - } - - return 0; -} Index: glibc-2.14/libio/fileops.c =================================================================== --- glibc-2.14.orig/libio/fileops.c +++ glibc-2.14/libio/fileops.c @@ -160,28 +160,20 @@ int _IO_new_file_close_it (fp) _IO_FILE *fp; { + int write_status; if (!_IO_file_is_open (fp)) return EOF; - int write_status; - if (_IO_in_put_mode (fp)) + if ((fp->_flags & _IO_NO_WRITES) == 0 + && (fp->_flags & _IO_CURRENTLY_PUTTING) != 0) write_status = _IO_do_flush (fp); - else if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL - && !_IO_in_backup (fp)) - { - off64_t o = _IO_SEEKOFF (fp, 0, _IO_seek_cur, 0); - if (o == WEOF) - write_status = EOF; - else - write_status = _IO_SYSSEEK (fp, o, SEEK_SET) < 0 ? EOF : 0; - } else write_status = 0; INTUSE(_IO_unsave_markers) (fp); int close_status = ((fp->_flags2 & _IO_FLAGS2_NOCLOSE) == 0 ? _IO_SYSCLOSE (fp) : 0); /* Free buffer. */ #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T