This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
BUG: STDC++ cin.readsome() blocks!
- From: Anton Lavrentiev <lavr at ncbi dot nlm dot nih dot gov>
- To: gcc-bugs at gcc dot gnu dot org, vakatov at ncbi dot nlm dot nih dot gov
- Date: Wed, 15 Oct 2003 09:58:48 -0400
- Subject: BUG: STDC++ cin.readsome() blocks!
- Organization: NIH/NLM/NCBI
Hi GCC-team,
There is unexpected behavior of cin.readsome(), when stdin is not
a file but a (network) pipe that is being fed in batches.
readsome() called on such cin blocks and tries to read exactly
4096 bytes (that the pipe might not have at the moment).
The backtrace shows the following calling sequence:
0x40dab654: __read + 0x14 (0, 40ad1000, 1000, 40d50e00, 40e02de0, 1000000) + 10
0x40d50e1d: _IO_file_read + 0x29 (40e00060, 40ad1000, 1000, 40d50706, 40e00060, 811bd30) + 30
0x40d50736: _IO_new_file_underflow + 0x15e (40e00060, 811bd30, 1000, 40d518a9, 40e02de0, 0) + 10
0x40d51996: __underflow + 0xfa (40e00060, 811bd30, 1000, 40d510c6, 40e02de0, 811bd30) + 20
0x40d5118f: _IO_file_xsgetn + 0xd7 (40e00060, 811bd30, 1000, 40d51cbd, 40e02de0, 40cb7240) + 10
0x40d51ce2: _IO_sgetn + 0x32 (40e00060, 811bd30, 1000, 40d47c42, 40aa68c0, 40cb7240) + 30
0x40d47cbd: _IO_fread + 0x89 (811bd30, 1, 1000, 40e00060, 816c1d0, 40aa68c0)
0x402d4c28 std::__basic_file<char>::xsgetn(char*, int) + 0x28 (80ffb18, 811bd30, 1000, 402d4ffe, 0, 1e0) + 10
0x402d50d4: std::basic_filebuf<char, std::char_traits<char> >::underflow() + 0xe4 (40cb7240, 40cb6f40, bfffd408, 8075a2f, 1000, 40cb6f40)
0x402d4f26: std::basic_filebuf<char, std::char_traits<char> >::showmanyc() + 0x26 (40cb7240, 40009e40, 4097dc0c, 8, 4068f440, 400151a0)
0x4068f479: std::basic_streambuf<char, std::char_traits<char> >::in_avail() + 0x39 (40cb7240, 40cb6f40, 1, 400916d0, bfffd468, 40009e40) + 10
0x4068f34f: std::istream::readsome(char*, int) + 0x4f (40cb6f40, 8182798, 1000, 400ab610, bfffd488, 40009e40) + 10
_IO_file_xsgetn() keeps calling ::read() syscall [via _IO_new_file_underflow] even when
some data was read on a previous iteration. That's because xsgetn() wants to see
exactly as many as requested number of bytes taken from file (0x1000 == 4096).
But cin (and perhaps any other named FS object like a named pipe) is not necessarily
a regular file, which can work in assumption that either the requested number of bytes
will be read, or EOF will be seen. What happens here is, ::read() from the first
iteration in _IO_file_xsgetn() returns less than 4096 bytes, then called again
::read() just blocks. There is no more data in the pipe, and thus readsome()
blocks. Overall, blocking is not the way readsome() is supposed to work,
according to the standard.
Perhaps, calling xsgetn() from showmanyc() is not a good solution in finding
how many bytes are available from the input sequence at the moment.
libio is unchanged with respect to this behavior in both versions 3.0.4 and 3.3.1.
Thanks for looking into this.
Anton Lavrentiev
for cpp-core group
NIH/NLM/NCBI
Bethesda, MD 20894