Bug 79820 - std::ifstream sets errno to zero
Summary: std::ifstream sets errno to zero
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: unknown
: P3 normal
Target Milestone: 5.5
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-03-02 19:09 UTC by Maurice Bos
Modified: 2017-09-13 16:43 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2017-03-02 00:00:00


Attachments
patch (265 bytes, patch)
2017-03-13 20:40 UTC, niXman
Details | Diff
patch (265 bytes, patch)
2017-03-14 13:55 UTC, niXman
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Maurice Bos 2017-03-02 19:09:18 UTC
https://gcc.gnu.org/onlinedocs/libstdc++/manual/errno.html says errno is never set to zero by libstdc++:

"The C and POSIX standards guarantee that errno is never set to zero by any library function. The C++ standard has less to say about when errno is or isn't set, but libstdc++ follows the same rule and never sets it to zero."

However, libstdc++-v3/config/io/basic_file_stdio.cc sets errno to zero in __basic_file<char>::sys_open (currently line 199). I guess errno is set to zero because sync() two lines below isn't guaranteed to update errno, in which case the loop might run forever if errno happened to be EINTR.

Maybe errno should only be set to zero in the case when it is EINTR, the only problematic case, and left untouched otherwise.
Comment 1 Jonathan Wakely 2017-03-02 19:33:49 UTC
I think we should capture the previous value of errno and restore it. I thought I checked for all places this was needed but maybe I only looked in the include and src sub-directories, not the config one.
Comment 2 niXman 2017-03-13 20:40:35 UTC
Created attachment 40966 [details]
patch
Comment 3 Jonathan Wakely 2017-03-13 21:33:43 UTC
Comment on attachment 40966 [details]
patch

It's quite possible that "errno" is a macro for something called "__errno" on some systems, so this would fail to compile. I suggest something like __save_errno instead, and it also needs to be done on line 275.
Comment 4 niXman 2017-03-13 22:28:51 UTC
(In reply to Jonathan Wakely from comment #3)

> and it also needs to be done on line 275.

why?
line 275: https://gcc.gnu.org/viewcvs/gcc/trunk/libstdc%2B%2B-v3/config/io/basic_file_stdio.cc?view=markup#l275
Comment 5 Jonathan Wakely 2017-03-14 13:44:59 UTC
Sorry, I was looking at gcc-6-branch which sets errno=0 in close(), but I removed that on trunk for PR 65411.
Comment 6 niXman 2017-03-14 13:55:14 UTC
Created attachment 40970 [details]
patch

done.
Comment 7 Jonathan Wakely 2017-08-08 19:44:14 UTC
The bug title says std::ifstream sets errno to zero, but it should never run stdio_filebuf::sys_open. Do you have a testcase for this?

We should still fix it even if it only affects a non-standard extension, but it's probably not worth backporting if it doesn't affect std::ifstream.
Comment 8 Jonathan Wakely 2017-08-09 17:52:43 UTC
Author: redi
Date: Wed Aug  9 17:52:10 2017
New Revision: 250993

URL: https://gcc.gnu.org/viewcvs?rev=250993&root=gcc&view=rev
Log:
PR libstdc++/81751 don't call fflush(NULL)

	PR libstdc++/79820
	PR libstdc++/81751
	* config/io/basic_file_stdio.cc (sys_open(FILE*, ios_base::openmode)):
	Call fflush on the stream instead of calling sync() while _M_cfile is
	null. Restore original value of errno.
	* testsuite/ext/stdio_filebuf/char/79820.cc: New.
	* testsuite/ext/stdio_filebuf/char/81751.cc: New.

Added:
    trunk/libstdc++-v3/testsuite/ext/stdio_filebuf/char/79820.cc
    trunk/libstdc++-v3/testsuite/ext/stdio_filebuf/char/81751.cc
Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/config/io/basic_file_stdio.cc
Comment 9 Jonathan Wakely 2017-08-09 18:09:39 UTC
Fixed for GCC 8.
Comment 10 Jonathan Wakely 2017-09-04 16:53:02 UTC
Author: redi
Date: Mon Sep  4 16:52:30 2017
New Revision: 251676

URL: https://gcc.gnu.org/viewcvs?rev=251676&root=gcc&view=rev
Log:
PR libstdc++/81751 don't call fflush(NULL)

Backport from mainline
2017-08-09  Jonathan Wakely  <jwakely@redhat.com>

	PR libstdc++/79820
	PR libstdc++/81751
	* config/io/basic_file_stdio.cc (sys_open(FILE*, ios_base::openmode)):
	Call fflush on the stream instead of calling sync() while _M_cfile is
	null. Restore original value of errno.
	* testsuite/ext/stdio_filebuf/char/79820.cc: New.
	* testsuite/ext/stdio_filebuf/char/81751.cc: New.

Added:
    branches/gcc-6-branch/libstdc++-v3/testsuite/ext/stdio_filebuf/char/79820.cc
    branches/gcc-6-branch/libstdc++-v3/testsuite/ext/stdio_filebuf/char/81751.cc
Modified:
    branches/gcc-6-branch/libstdc++-v3/ChangeLog
    branches/gcc-6-branch/libstdc++-v3/config/io/basic_file_stdio.cc
Comment 11 Jonathan Wakely 2017-09-04 17:09:37 UTC
Author: redi
Date: Mon Sep  4 17:09:05 2017
New Revision: 251680

URL: https://gcc.gnu.org/viewcvs?rev=251680&root=gcc&view=rev
Log:
PR libstdc++/81751 don't call fflush(NULL)

Backport from mainline
2017-08-09  Jonathan Wakely  <jwakely@redhat.com>

	PR libstdc++/79820
	PR libstdc++/81751
	* config/io/basic_file_stdio.cc (sys_open(FILE*, ios_base::openmode)):
	Call fflush on the stream instead of calling sync() while _M_cfile is
	null. Restore original value of errno.
	* testsuite/ext/stdio_filebuf/char/79820.cc: New.
	* testsuite/ext/stdio_filebuf/char/81751.cc: New.

Added:
    branches/gcc-5-branch/libstdc++-v3/testsuite/ext/stdio_filebuf/char/79820.cc
    branches/gcc-5-branch/libstdc++-v3/testsuite/ext/stdio_filebuf/char/81751.cc
Modified:
    branches/gcc-5-branch/libstdc++-v3/ChangeLog
    branches/gcc-5-branch/libstdc++-v3/config/io/basic_file_stdio.cc
Comment 12 Jonathan Wakely 2017-09-04 17:21:12 UTC
Fixed for 5.5, 6.5 and 7,.3
Comment 13 Aldy Hernandez 2017-09-13 16:43:42 UTC
Author: aldyh
Date: Wed Sep 13 16:43:11 2017
New Revision: 252358

URL: https://gcc.gnu.org/viewcvs?rev=252358&root=gcc&view=rev
Log:
PR libstdc++/81751 don't call fflush(NULL)

	PR libstdc++/79820
	PR libstdc++/81751
	* config/io/basic_file_stdio.cc (sys_open(FILE*, ios_base::openmode)):
	Call fflush on the stream instead of calling sync() while _M_cfile is
	null. Restore original value of errno.
	* testsuite/ext/stdio_filebuf/char/79820.cc: New.
	* testsuite/ext/stdio_filebuf/char/81751.cc: New.

Added:
    branches/range-gen2/libstdc++-v3/testsuite/ext/stdio_filebuf/char/79820.cc
    branches/range-gen2/libstdc++-v3/testsuite/ext/stdio_filebuf/char/81751.cc
Modified:
    branches/range-gen2/libstdc++-v3/ChangeLog
    branches/range-gen2/libstdc++-v3/config/io/basic_file_stdio.cc