Bug 14979

Summary: fifo's select(2)/poll(2) handler is broken in FreeBSD-3.X
Product: Base System Reporter: seva <seva>
Component: kernAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 3.2-RELEASE   
Hardware: Any   
OS: Any   

Description seva 1999-11-18 16:10:00 UTC
	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
Comment 1 Bruce Evans 1999-11-18 18:26:42 UTC
> >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
Comment 2 Bruce Evans freebsd_committer freebsd_triage 1999-11-20 13:15:02 UTC
State Changed
From-To: open->closed

The submitter agrees with me the bug is in the bug report.