Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com X-Authentication-Warning: koeberg.lysator.liu.se: astrand owned process doing -bs Date: Fri, 10 Dec 2004 00:41:29 +0100 (MET) From: Peter Astrand To: cygwin AT cygwin DOT com Subject: Re: short fread(), but no ferror/feof In-Reply-To: Message-ID: References: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=iso-8859-1 X-Spam-Checker-Version: SpamAssassin 2.63-lysator_fetto_1.2 (2004-01-11) on fetto.lysator.liu.se X-Spam-Level: X-Spam-Status: No, hits=-2.1 required=5.0 tests=AWL,J_CHICKENPOX_53,TW_RR autolearn=no version=2.63-lysator_fetto_1.2 Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from QUOTED-PRINTABLE to 8bit by delorie.com id iB9Nfp54019462 >> I've discovered that fread(ptr, size, nitems, stream) sometimes returns a >> value less than "nitems", but does not set feof() nor ferror(). As I >A simple, compilable test case with results shown on both linux and >cygwin would prove your theory. Here you go; example follows. Test run on Linux: --- Got 66 bytes: /bin/ls: /somebogus: Filen eller katalogen finns inte /etc/passwd |EOF has been reached. --- Test run on Cygwin: --- $ ./a.exe Got 9 bytes: /bin/ls: | --- As you can see, the result is partial, and there is no EOF nor error. I guess this is the problem described at http://sources.redhat.com/ml/newlib/2004/msg00477.html. Perhaps you can apply the suggested patch? Example code follows. #include #include #include #include void checked_close(int fd) { if (close(fd) == -1) { perror("close"); exit(1); } } void checked_pipe(int filedes[2]) { if (pipe(filedes) == -1) { perror("filedes"); exit(1); } } int checked_dup2(int oldfd, int newfd) { int ret; if ((ret = dup2(oldfd, newfd)) == -1) { perror("dup2"); exit(1); } return ret; } int main() { int c2p[2]; int errpipe[2]; pid_t pid; char errpipe_buf[16]; char buf[16394]; ssize_t errpipe_count; size_t count; FILE *output; checked_pipe(c2p); checked_pipe(errpipe); fcntl(errpipe[1], F_SETFD, FD_CLOEXEC); pid = fork(); switch (pid) { case -1: perror("fork"); exit(1); break; case 0: /* child */ checked_close(c2p[0]); checked_close(errpipe[0]); dup2(c2p[1], 1); dup2(c2p[1], 2); checked_close(c2p[1]); execlp("/bin/ls", "/bin/ls", "/etc/passwd", "/somebogus"); /* If we are still around, exec failed */ write(errpipe[1], "1", 1); _exit(255); break; default: /* parent */ break; } checked_close(errpipe[1]); checked_close(c2p[1]); errpipe_count = read(errpipe[0], errpipe_buf, 1); switch (errpipe_count) { case -1: perror("read"); exit(1); break; case 0: /* EOF, good */ break; default: /* Our "1", exec failed */ fprintf(stderr, "exec in child failed\n"); exit(1); break; } /* now read output from child, via a FILE stream */ if ((output = fdopen(c2p[0], "rb")) == NULL) { perror("fdopen"); exit(1); } setvbuf(output, 0, _IONBF, 0); clearerr(output); count = fread(buf, 1, sizeof(buf), output); if (count >= 0) { fprintf(stderr, "Got %d bytes:\n", count); fprintf(stderr, "%s|", buf); } if (feof(output)) { fprintf(stderr, "EOF has been reached.\n"); } if (ferror(output)) { fprintf(stderr, "An error occured.\n"); } return 0; } /Peter Åstrand -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/