This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC 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]

BUG: STDC++ cin.readsome() blocks!


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]