| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#1
|
| 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 |
|
#2
|
| "David Mathog" 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 |
|
#3
|
| 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 |
|
#4
|
| In article David Mathog > 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 *** |
|
#5
|
| Barry Margolin wrote: > > Does the O_NONBLOCK option to open(2) help? (Sheepishly) Yes, that did it. Thanks, David Mathog |
|
#6
|
| "David Mathog" 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 |
| Thread Tools | |
| Display Modes | |
| ||||
| 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 | |