| Summary: | fifo's select(2)/poll(2) handler is broken in FreeBSD-3.X | ||
|---|---|---|---|
| Product: | Base System | Reporter: | seva <seva> |
| Component: | kern | Assignee: | freebsd-bugs (Nobody) <bugs> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 3.2-RELEASE | ||
| Hardware: | Any | ||
| OS: | Any | ||
> >Description:
>
> when fifo (maden by mkfifo(1)) has select(2)ed or poll(2)ed
> select(2) and poll(2) returns without timeout even
> fifo has no bytes to read.
>
> In FreeBSD 2.X and NetBSD 1.4.1 there is timeout as expected.
I think the timeout is unexpected. read() on a fifo with no writers
was broken in FreeBSD-2.x. I fixed this, and the select() and poll()
behaviour changed automatically to match the read() behaviour.
Some details: POSIX.1 requires read() on a fifo with no writers to
return 0 without blocking. FreeBSD-2.x did extra work to break this
in some cases. IIRC, the only broken case was for fifos that never
had a writer. POSIX doesn't distinguish this case. Sockets have
flags to control the behaviour precisely, but these are not available
for fifos.
select() and poll() return immediately because there is an interesting
state to read, namely EOF.
At least some versions of Linux and Sunos have special handling for
select() on fifos. I think they break select() to do what you want.
Bruce
State Changed From-To: open->closed The submitter agrees with me the bug is in the bug report. |
when fifo (maden by mkfifo(1)) has select(2)ed or poll(2)ed select(2) and poll(2) returns without timeout even fifo has no bytes to read. In FreeBSD 2.X and NetBSD 1.4.1 there is timeout as expected. Fix: I don't know. How-To-Repeat: # mkfifo fifo # cat readfifo.select.c #include <fcntl.h> #include <err.h> #include <errno.h> #include <sys/types.h> #include <sys/time.h> #include <unistd.h> #include <stdio.h> #include <string.h> int main(int argc,char **argv) { int fd; char *fn="fifo"; if(argc>1) fn=*(argv+1); if((fd=open(fn,O_RDONLY|O_NONBLOCK))<0) err(errno,"can't open %s",fn); for(;;){ fd_set fds; int r; struct timeval tv; size_t sz; char b[64]; tv.tv_sec=5; tv.tv_usec=0; FD_ZERO(&fds); FD_SET(fd,&fds); r=select(FD_SETSIZE,&fds,NULL,NULL,&tv); if(r<0) err(errno,"select return %d ",r); if(r==0){ fputs("timeout\n",stderr); continue; } sz=read(fd,b,63); if(sz<0) err(errno,"read fifo return %d",sz); if(!sz){ fputs("read null bites\n",stderr); continue; } b[sz]='\0'; puts(b); fflush(stdout); } } # cat readfifo.poll.c #include <fcntl.h> #include <err.h> #include <errno.h> #include <sys/types.h> #include <sys/uio.h> #include <unistd.h> #include <poll.h> #include <stdio.h> int main(int argc,char **argv) { int fd; char *fn="fifo"; if(argc>1) fn=*(argv+1); fd=open(fn,O_RDONLY|O_NONBLOCK); if(fd<0) err(errno,"cannot open %s",fn); for(;;){ struct pollfd pfd; int pr; size_t sz; char b[64]; pfd.fd=fd; /*pfd.events=POLLRDNORM;*/ pfd.events=POLLIN; pr=poll(&pfd,1,5000); if(pr==-1) err(errno,"error in poll"); if(!pr){ fputs("timeout\n",stderr); continue; } puts("reading");fflush(stdout); sz=read(fd,b,63); if(sz<0) err(errno,"cannot read"); if(!sz){ fputs("read null bytes\n",stderr); continue; } b[sz]='\0'; puts(b); fflush(stdout); } } # make readfifo.select # make readfifo.poll # ./readfifo.select