Path: utzoo!attcan!telly!eci386!clewis From: clewis@eci386.uucp (Chris Lewis) Newsgroups: comp.lang.perl Subject: Re: print return code bug... Message-ID: <1990May9.163022.29847@eci386.uucp> Date: 9 May 90 16:30:22 GMT References: <1990May4.202029.9341@eci386.uucp> <7996@jpl-devvax.JPL.NASA.GOV> Reply-To: clewis@eci386.UUCP (Chris Lewis) Organization: Elegant Communications Inc., Toronto, Canada Lines: 55 In article <7996@jpl-devvax.JPL.NASA.GOV> lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) writes: > In article <1990May4.202029.9341@eci386.uucp> clewis@eci386 (Chris Lewis) writes: > Hmm, apparently fwrite() isn't checking the error status if it has to do a > flush. Nothing much I can do about that. Hmm, I've just checked our fwrite and it does successfully check the return code, as in this *does* work: X #include X char buffer[30]; X main() { X FILE *f = fopen("/tmp/TRASH", "w"); X int len; X ulimit(2, 20L); /* get the write to blow */ X while((len = fwrite(buffer, 1, sizeof(buffer), f)) == sizeof(buffer)); X fclose(f); X printf("%d\n", len); X } According to the manual page, fwrite returns the number of items successfully written - zero for none. I've tested the above with the buffer set to 30 and BUFSIZ (from stdio.h) and it works properly either way. ulimit is a way to get System V to fail on a write after an open without the more draconian approach of blowing the file system. I've got a somewhat simpler Perl script that doesn't blow your file system either (this is a shell script): X ulimit 1 X perl -e 'while (0 != printf("Hello\n")) { ; }' > /tmp/TRASH2 perl writes 512 bytes and keeps eating CPU .... Using the errno = 0; fwrite... if (errno != 0) is extremely unsafe (as someone else has already pointed out). I should go look at the perl source and see if I can see what's happening. Hmm, a quick look shows an unchecked fprintf in doio's "do_print", but I don't think that clause is involved.... The fwrites in perl's *.c's appear properly checked. I have thought a bit further on this, and I have a suspicion that this isn't really sufficient to check for write failures - since the close() could do a flush, it could fail too. Perhaps perl's close routine should return a value that indicates write *or* pipe failure (the latter is already supported by explicitly testing $?). Maybe by testing ferror()? -- Chris Lewis, Elegant Communications Inc, {uunet!attcan,utzoo}!lsuc!eci386!clewis Ferret mailing list: eci386!ferret-list, psroff mailing list: eci386!psroff-list