use of select() on FIFO after it has closed

This is a discussion on use of select() on FIFO after it has closed within the Unix forums, part of the Operating Systems category; 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 ...

Go Back   Unix Forum > Operating Systems > Unix

FixUnix.com - Unix Linux Forums

Register FAQ Calendar Search Today's Posts Mark Forums Read
  #1  
Old 02-23-2008, 12:54 PM
Default 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
Reply With Quote
  #2  
Old 02-23-2008, 02:26 PM
Default Re: use of select() on FIFO after it has closed

"David Mathog" wrote in message
news:fppq52$ob4$1-at-naig.caltech.edu...
[snip]
> 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()?


The potential problem with closing and reopening the FIFO is that there is a
window between read() == 0 and close() where data written will be thrown
away.

An alternative is to open the FIFO for writing immediately after opening it
for reading, and leave both descriptors open (opening it O_RDWR may work;
the behaviour is unspecified by POSIX). This means you will never see EOF
(useful in some cases).

Alex


Reply With Quote
  #3  
Old 02-25-2008, 02:52 PM
Default Re: use of select() on FIFO after it has closed

Alex Fraser wrote:

> An alternative is to open the FIFO for writing immediately after opening it
> for reading, and leave both descriptors open (opening it O_RDWR may work;
> the behaviour is unspecified by POSIX). This means you will never see EOF
> (useful in some cases).


I went this route. Now it opens the file, checks the fd with fstat() to
see if it is a FIFO, and if it is, it opens the same file for write.

Unfortunately it (still) locks on the first open() of the FIFO unless
there is already data waiting there. I do not think there is a way
around that, since the program cannot set read nonblocking until it has
a read fd, and it cannot get a read fd until the file is opened. The
program could use stat() first to see if it is a FIFO before opening it
for read, and do the open for write first, then push a byte or two into
the FIFO so the open for read won't block. But that isn't safe, since
the program has no way of knowing if there is data in the FIFO at that
point. Better to live with the block on open for read I guess.

Thanks,

David Mathog
Reply With Quote
  #4  
Old 02-25-2008, 09:05 PM
Default Re: use of select() on FIFO after it has closed

In article ,
David Mathog wrote:

> Alex Fraser wrote:
>
> > An alternative is to open the FIFO for writing immediately after opening it
> > for reading, and leave both descriptors open (opening it O_RDWR may work;
> > the behaviour is unspecified by POSIX). This means you will never see EOF
> > (useful in some cases).

>
> I went this route. Now it opens the file, checks the fd with fstat() to
> see if it is a FIFO, and if it is, it opens the same file for write.
>
> Unfortunately it (still) locks on the first open() of the FIFO unless
> there is already data waiting there. I do not think there is a way
> around that, since the program cannot set read nonblocking until it has
> a read fd, and it cannot get a read fd until the file is opened. The
> program could use stat() first to see if it is a FIFO before opening it
> for read, and do the open for write first, then push a byte or two into
> the FIFO so the open for read won't block. But that isn't safe, since
> the program has no way of knowing if there is data in the FIFO at that
> point. Better to live with the block on open for read I guess.


Does the O_NONBLOCK option to open(2) help?

--
Barry Margolin, barmar-at-alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
Reply With Quote
  #5  
Old 02-26-2008, 11:01 AM
Default Re: use of select() on FIFO after it has closed

Barry Margolin wrote:
>
> Does the O_NONBLOCK option to open(2) help?


(Sheepishly) Yes, that did it.

Thanks,

David Mathog
Reply With Quote
  #6  
Old 02-27-2008, 01:29 AM
Default Re: use of select() on FIFO after it has closed

"David Mathog" wrote in message
news:fq1gl6$11o$1-at-naig.caltech.edu...
> Barry Margolin wrote:
>>
>> Does the O_NONBLOCK option to open(2) help?

>
> (Sheepishly) Yes, that did it.


Ignoring O_RDWR (undefined by POSIX for a FIFO), open(fifo, O_RDONLY |
O_NONBLOCK) then open(fifo, O_WRONLY) is the only way because open(fifo,
O_WRONLY) blocks until the FIFO is open for reading and open(fifo, O_WRONLY
| O_NONBLOCK) returns an error (ENXIO) if the FIFO is not open for reading.

Alex


Reply With Quote
Reply


Thread Tools
Display Modes

LinkBacks (?)
LinkBack to this Thread: http://fixunix.com/unix/350803-use-select-fifo-after-has-closed.html

Posted By For Type Date
codeblog This thread Refback 04-04-2008 03:37 PM
Graphics Planet This thread Refback 03-10-2008 12:50 PM
Planet Inkscape This thread Refback 03-10-2008 06:59 AM
Planet Ubuntu This thread Refback 03-10-2008 05:09 AM
Planet Ubuntu This thread Refback 03-10-2008 03:18 AM
The Linux Index » Kees Cook: using select on a fifo This thread Pingback 03-09-2008 09:07 PM
codeblog » using select on a fifo This thread Pingback 03-09-2008 08:00 PM


All times are GMT -5. The time now is 03:58 PM.

In an effort to better serve ads to our visitors, cookies are used on Fixunix.com. For more information, check out our Privacy Policy.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO 3.1.0
Ad Management by RedTyger