Test case: #include <cstdlib> #include <iostream> #include <unistd.h> #include <string.h>
int main(int argc, char * argv[]) { if (argc != 2) { std::cerr << "Usage: ./test writer | ./test reader" << std::endl; return 2; } if (strcmp("reader", argv[1]) == 0) { // note, no input/output is allowed to happen before this call. std::cin.sync_with_stdio(false); int length = 0; while (std::cin.good()) { char buffer[BUFSIZ]; (void)std::cin.read(buffer, sizeof(buffer)); length += std::cin.gcount(); } if (length == 82) { std::cerr << "Success" << std::endl; return EXIT_SUCCESS; } else { std::cerr << "Failure, length is " << length << std::endl; return EXIT_FAILURE; } } else if (strcmp("writer", argv[1]) == 0) { std::cout << "1234567890123456789012345678901234567890" << std::endl; sleep(1); std::cout << "1234567890123456789012345678901234567890" << std::endl; return EXIT_SUCCESS; } else { std::cerr << "Bad argument" << std::endl; return 3; } } Analysis: When sync_with_stdio(false), cin uses basic_filebuf which is based on __basic_file, and its xsgetn function: streamsize __basic_file<char>::xsgetn(char* __s, streamsize __n) { streamsize __ret; do __ret = read(this->fd(), __s, __n); while (__ret == -1L && errno == EINTR); return __ret; } When fd() refers to a pipe, this function may return before __n characters are read, but also before an end-of-file is detected (say if the pipe supplier just isn't finished yet). For the Posix read function this is a normal operating mode. However for one client of this function (basic_filebuf::xsgetn, called by istream::read), if less than __n characters are returned, this represents an error, subsequently setting failbit|eofbit in the istream. The fix is to change __basic_file<char>::xsgetn to hang in there until either EOF is detected, or until there is a non-recoverable error. I believe the following rewrite will do the job: streamsize __basic_file<char>::xsgetn(char* __s, streamsize __n) { streamsize __ret = 0; for (streamsize __i; __n > 0; __ret += __i, __s += __i, __n -= __i) { __i = read(this->fd(), __s, __n); if (__i == 0) break; if (__i == -1) { if (!(errno == EINTR || errno == EAGAIN)) break; __i = 0; } } return __ret; } -- Summary: __basic_file<char>::xsgetn does not deal well with pipes Product: gcc Version: 4.0.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: hhinnant at apple dot com GCC host triplet: Mac OS 10.4.5 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27168