attaching.. On 18 February 2013 20:58, Bernhard Reutner-Fischer <rep.dot....@gmail.com> wrote: > On 25 March 2012 07:54, Mike Frysinger <vap...@gentoo.org> wrote: >> fixed the style & pushed. thanks all! it's nice we have people versed in >> esoteric low level aspects nowadays. > > hmz, revisiting.. > To recap: > > On 7 February 2011 02:41, Denys Vlasenko <vda.li...@googlemail.com> wrote: >> Currently, uclibc retains buffered data on stdio write errors, >> and subsequent fclose and fflush will try to write it out again >> (in most cases, in vain). >> >> Which results in something like this: >> >> On Wednesday 26 January 2011 13:21, Baruch Siach wrote: >>> Hi busybox list, >>> >>> I'm running the following command under strace (thanks Rob): >>> >>> echo 56 > /sys/class/gpio/export >>> >>> and I see the following output: >>> >>> write(1, "56\n", 3) = -1 EBUSY (Device or resource busy) >>> write(1, "5", 1) = 1 >>> >>> The first EBUSY is OK, since GPIO 56 is already requested. But the second >>> write() attempt seems strange, and leads to an unwanted outcome. GPIO 5 gets >>> exported. >> >> >> This patch prevents that. > > This rather sounds to me that this second write with an odd length is wrong, > no? > IIUC the patch (867bac0c) that went in for this issue is causing > https://bugs.uclibc.org/5156 (fclose and fflush do not report write failures) > > I am attaching denys.c, i think this is the testcase you had in mind > in your patch that Mike applied as > 867bac0c750401d2f429ad6bb066498c3b8b35c1 > The attached fulltest.c is from above mentioned PR5156. > Also attached is a patch that seems to cure PR5156 (the hunk against > _wcommit.c is your rephrased patch cited below, not needed for 5156 > though) and that basically reverts your 867bac0c. > With this patch we would get: > $ ./denys_uc > /dev/null > Hi there 1 > Hi there 2 > $ ./denys_uc 2> /dev/null > $ ./denys_glibc > /dev/null > Hi there 1 > Hi there 2 > $ ./denys_glibc 2> /dev/null > $ ./fulltest_glibc > fwrite: x=4, errno=25 > fflush: y=-1, errno=28 > fputc 1: x=88, errno=25 > fflush: y=-1, errno=28 > fputc 2: x=88, errno=25 > fclose: y=-1, errno=28 > # the ENOTYPEWRITER i dislike > $ ./fulltest > fwrite: x=4, errno=0 > fflush: y=-1, errno=28 > fputc 1: x=88, errno=28 > fflush: y=-1, errno=28 > fputc 2: x=88, errno=28 > fclose: y=-1, errno=28 > so 5156 would be fixed, we'd diverge from glibc in the type-writer > errno (which is imo ok) and (since we fully buffer fwrite) do not > errno the fwrite. > I guess it would not fix your (line-buffered, i assume?) gpio echo, would it? > >> -- >> vda >> >> diff -d -urpN uClibc.0/libc/stdio/_wcommit.c uClibc.1/libc/stdio/_wcommit.c >> --- uClibc.0/libc/stdio/_wcommit.c 2011-02-07 00:04:34.000000000 +0100 >> +++ uClibc.1/libc/stdio/_wcommit.c 2011-02-07 00:55:24.000000000 +0100 >> @@ -20,7 +20,18 @@ size_t attribute_hidden __stdio_wcommit( >> >> __STDIO_STREAM_VALIDATE(stream); >> >> - if ((bufsize = __STDIO_STREAM_BUFFER_WUSED(stream)) != 0) { >> + /* Note: we do not write anything if write error has been detected. >> + * Otherwise, stdio user has no way to prevent retries after >> + * failed write - and some users do want to not have any retries! >> + * IOW: if write errored out, neither fflush nor fclose should >> + * try to write buffered data. >> + * clearerr may be used to enable retry if needed. >> + */ >> + >> + bufsize = __STDIO_STREAM_BUFFER_WUSED(stream); >> + if (bufsize != 0 >> + && !(stream->__modeflags & __FLAG_ERROR) >> + ) { >> stream->__bufpos = stream->__bufstart; >> __stdio_WRITE(stream, stream->__bufstart, bufsize); >> }
#include <unistd.h> #include <stdio.h> #include <errno.h> #include <assert.h>
int main(void) { int i; int oldfd = fileno(stderr); int newfd = fileno(stdout); i = close(newfd); assert(i == 0); i = printf("Hi there 1\n"); assert(i == 11); i = ferror(stdout); assert(i == 0); i = dup2(oldfd, newfd); assert(i == newfd); i = printf("Hi there 2\n"); assert(i == 11); return 0; }
#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> int main (int argc, char **argv) { FILE *f; int x, y; char str[1024]; memset (str, 'X', sizeof str); /* subcase 0 */ f = fopen ("/dev/full", "w"); assert (f); x = fwrite (&str, 1024/4, 4, f); printf("fwrite: x=%d, errno=%d\n", x, errno); y = fflush (f); printf("fflush: y=%d, errno=%d\n", y, errno); assert (x == EOF || y == EOF); fclose (f); /* subcase 1 */ f = fopen ("/dev/full", "w"); assert (f); x = fputc ('X', f); printf("fputc 1: x=%d, errno=%d\n", x, errno); y = fflush (f); printf("fflush: y=%d, errno=%d\n", y, errno); assert (x == EOF || y == EOF); fclose (f); /* subcase 2 */ f = fopen ("/dev/full", "w"); assert (f); x = fputc ('X', f); printf("fputc 2: x=%d, errno=%d\n", x, errno); y = fclose (f); printf("fclose: y=%d, errno=%d\n", y, errno); assert (x == EOF || y == EOF); return EXIT_SUCCESS; }
uClibc-redo-867bac0c750401d2f429ad6bb066498c3b8b35c1.00.patch
Description: Binary data
_______________________________________________ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc