
02-23-2008, 06:54 PM
|
| Junior Member | | Join Date: Sep 2009
Posts: 0
| |
use of select() on FIFO after it has closed Set up a fifo like this from bash:
mkfifo /tmp/testfifo
inside a program open it, which gets an fd, set that fd nonblocking
(because of other stuff going on on other fd's which are not shown in
this example) then enter a program which has a loop containing
(simplified from the original):
FD_CLEAR(&read_set);
FD_SET(fd, &read_set);
select(fd+1,&read_set,NULL,NULL,NULL);
if(FD_ISSET(fd,&read_set)){
ret = read(fd, addr, n);
if(ret>0){
(void) fprintf(stdout,"Read %s\n",addr);
}
else if(ret < 0){
(void) fprintf(stdout,"Error %d\n",errno);
}
else {
(void) fprintf(stdout,"File closed\n");
}
}
Here is where it gets strange. At first this works as expected, it
gets to the select() and waits for input on the FIFO. If from another
shell one then does:
echo "word" >/tmp/testfifo
Select sees that data is available and returns, FD_ISSET is true,
read() gets the data, and finally fprintf emits
Read word
So far so good. However, then things go south. Because the echo
"closed" the fifo, select() sees it in End of File (which is an event)
and comes back immediately, FD_ISSET is true, and read returns 0 (== end
of file). So the program begins to spew
File closed
File closed
....
as fast as it can. If while this is going on from another shell
one does:
echo "another word" >/tmp/testfifo
the output will look like this
....
File closed
Read another word
File closed
File closed
....
In this case EOF does not indicate the end of input, that is
triggered by a particular "End of Stream" string sent to the fifo.
The question is, what is the most portable way to make the select() stop
coming back immediately? If the application closes and reopens the FIFO
it will go back to the original state where it will wait at the
select(). Is there a better way, perhaps using fcntl()?
Thanks,
David Mathog |