This is follow-up of my investigation and proposed fix at http://old.nabble.com/named-pipe-is-borken-and-proposed-fix-td31753483.html#a31753483
The testing programs worked well with glibc, but failed in uClibc-0.9.32. As Laurent pointed out, this is undefined in standard. For the sake of application developers who want to port apps from glibc to uClibc without worrying about the subtle difference, it is nice to help them out with following patch. The problem is that FIFO is a special file type, and the conventional EOF is useless, and should not be set. The fix is to avoid setting __FLAG_EOF for stream associated with FIFO file after all senders were closed. Signed-off-by: Jian Peng <jipeng2...@gmail.com> --- libc/stdio/_READ.c | 29 ++++++++++++++++++++++++- libc/sysdeps/linux/common/bits/uClibc_stdio.h | 1 + 2 files changed, 29 insertions(+), 1 deletions(-) diff --git a/libc/stdio/_READ.c b/libc/stdio/_READ.c index 02601c0..2ecc920 100644 --- a/libc/stdio/_READ.c +++ b/libc/stdio/_READ.c @@ -6,7 +6,25 @@ */ #include "_stdio.h" +#include <sys/syscall.h> +#include <unistd.h> +#include <sys/stat.h> +#include "xstatconv.h" +#define __NR___syscall_fstat __NR_fstat +static __inline__ _syscall2(int, __syscall_fstat, int, fd, struct kernel_stat *, buf) + +int _my_fstat(int fd, struct stat *buf) +{ + int result; + struct kernel_stat kbuf; + + result = __syscall_fstat(fd, &kbuf); + if (result == 0) { + __xstat_conv(&kbuf, buf); + } + return result; +} /* Given a reading stream without its end-of-file indicator set and * with no buffered input or ungots, read at most 'bufsize' bytes @@ -44,7 +62,16 @@ size_t attribute_hidden __stdio_READ(register FILE *stream, /* RETRY: */ if ((rv = __READ(stream, (char *) buf, bufsize)) <= 0) { if (rv == 0) { - __STDIO_STREAM_SET_EOF(stream); + struct stat stat; + + if( (stream->__modeflags & __FLAG_FIFOFILE) || + _my_fstat(stream->__filedes, &stat) >= 0) { + if(S_ISFIFO(stat.st_mode)) + stream->__modeflags |= __FLAG_FIFOFILE; + } + + if(!(stream->__modeflags & __FLAG_FIFOFILE)) + __STDIO_STREAM_SET_EOF(stream); } else { /* if (errno == EINTR) goto RETRY; */ __STDIO_STREAM_SET_ERROR(stream); diff --git a/libc/sysdeps/linux/common/bits/uClibc_stdio.h b/libc/sysdeps/linux/common/bits/uClibc_stdio.h index a8cf4eb..1d2cc11 100644 --- a/libc/sysdeps/linux/common/bits/uClibc_stdio.h +++ b/libc/sysdeps/linux/common/bits/uClibc_stdio.h @@ -331,6 +331,7 @@ struct __STDIO_FILE_STRUCT { #define __FLAG_FREEBUF 0x4000U #define __FLAG_LARGEFILE 0x8000U /* fixed! == 0_LARGEFILE for linux */ #define __FLAG_FAILED_FREOPEN __FLAG_LARGEFILE +#define __FLAG_FIFOFILE 0x1000U /* handle FIFO differently */ /* Note: In no-buffer mode, it would be possible to pack the necessary * flags into one byte. Since we wouldn't be buffering and there would -- 1.7.4.1 _______________________________________________ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc