blarsen@spider.uio.no (Bjorn Larsen) (05/30/91)
Yesterday, I wanted to use select(2) to wait on a number of FIFO's that were opened for reading. It turned out to be harder than I expected. Originally, the program opened the FIFO's with O_NONBLOCK, and tried to read them occationally. It turns out that select() on such a file descriptor returns immediately, indicating that the fd was ready. In a sense, that is true -- the fd is ready so far that I can take a read() on it without blocking. But what I expected select() to do was to tell me wether there was data on the FIFO, not wether it is possible to issue a read() on the fd. The program is a deamon, and the FIFO's will be opened and written to by other programs every once in a while. So opening the FIFO's for blocking read isn't such a hot idea eigther; it will cause the daemon to block, waiting for a process to open the FIFO for writing. So I came up with the following 'solution': int fd, wfd; /* Open the FIFO for nonblocking read */ fd = open("/tmp/FIFO", O_RDONLY|O_NONBLOCK); /* Open the FIFO for write (won't hang, since it is open for read) */ wfd = open("/tmp/FIFO", O_WRONLY); /* Close the read descriptor */ close(fd); /* Open the FIFO for blocking read */ fd = open("/tmp/FIFO", O_RDONLY); After these acrobatics, the file descriptor 'fd' can be used with select(). It seems to work OK, but is this the 'right' way to do this? Are there any sideeffects of this that I haven't thought about? And is there a more elegant way to go about it? --- Bjorn.Larsen@usit.uio.no "Specialization is for insects" University Centre for Information Technology - Lazarus Long University of Oslo, Norway
boyd@prl.dec.com (Boyd Roberts) (05/30/91)
Don't you just want to open the named pipe in non-blocking mode and then use fcntl(2) to turn off the non-blocking so that read and select work the way you want them to? Boyd Roberts boyd@prl.dec.com ``When the going gets wierd, the weird turn pro...''
les@chinet.chi.il.us (Leslie Mikesell) (05/30/91)
In article <BLARSEN.91May30090732@spider.uio.no> Bjorn.Larsen@usit.uio.no writes: >Yesterday, I wanted to use select(2) to wait on a number of FIFO's >that were opened for reading. It turned out to be harder than I >expected. [...] >So I came up with the following 'solution': > > int fd, wfd; > >/* Open the FIFO for nonblocking read */ > fd = open("/tmp/FIFO", O_RDONLY|O_NONBLOCK); > >/* Open the FIFO for write (won't hang, since it is open for read) */ > wfd = open("/tmp/FIFO", O_WRONLY); > >/* Close the read descriptor */ > close(fd); > >/* Open the FIFO for blocking read */ > fd = open("/tmp/FIFO", O_RDONLY); > >After these acrobatics, the file descriptor 'fd' can be used with >select(). I don't have select(), but I've always just opened the FIFO with O_RDWR on the reader side which (a) doesn't block during the open, and (b) does cause the read()s to continue to block for data instead of returning EOF after a writer has closed. This allows the writers to come and go as necessary. If you can arrange for every action the daemon is supposed to perform to be triggered by a write to the FIFO, you can just let the read block. Of course if you want to see EOF when the writer exits, you can't do it this way. I would expect select() to wake up when the last writer closes, so you would control seeing this by whether or not the reading process also opens for writing. However, if the reading process does not open for writing, after the FIFO has been opened and closed by a writer it will return EOF immediately instead of blocking whenever no writer has it open. Select() shouldn't block in this case either. Les Mikesell les@chinet.chi.il.us
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (06/03/91)
In article <BLARSEN.91May30090732@spider.uio.no> Bjorn.Larsen@usit.uio.no writes: > Originally, the program opened the FIFO's with O_NONBLOCK, and tried > to read them occationally. It turns out that select() on such a file > descriptor returns immediately, indicating that the fd was ready. In > a sense, that is true -- the fd is ready so far that I can take a > read() on it without blocking. But what I expected select() to do was > to tell me wether there was data on the FIFO, not wether it is > possible to issue a read() on the fd. select() normally tells you whether the I/O would block *if* the descriptor were blocking. Unfortunately, ``blocking'' has one meaning in System V, one meaning in BSD, two slightly different meanings in SunOS, and yet another slightly different meaning in POSIX---and select() only respects the BSD meaning. Don't expect select() to work properly if you combine different nonblocking mechanisms. Since you're using select(), you might as well not bother with NONBLOCK. Just make sure to select() before every I/O operation. (Beware that if there are multiple readers or writers on a pipe, select() can't guarantee that the I/O won't block a moment later. In that case you also have to set nonblocking before each I/O and unset it before select(). It's at times like this that I wish for VMS I/O.) ---Dan
gwc@root.co.uk (Geoff Clare) (06/04/91)
les@chinet.chi.il.us (Leslie Mikesell) writes: > I've always just opened the FIFO with O_RDWR >on the reader side which (a) doesn't block during the open, and (b) Although this works on most if not all current UNIX systems, it's not required by POSIX, so applications using this method may not work on some future systems. For maximum portability to current and future systems, I recommend using the following method to open both sides of a FIFO to do blocking I/O: fd_rd = open("FIFO", O_RDONLY|O_NONBLOCK); fd_wr = open("FIFO", O_WRONLY); flags = fcntl(fd_rd, F_GETFL); fcntl(fd_rd, F_SETFL, flags & ~O_NONBLOCK); with something like the following tucked away in a header: #ifndef _POSIX_SOURCE #define O_NONBLOCK O_NDELAY #endif -- Geoff Clare <gwc@root.co.uk> (Dumb American mailers: ...!uunet!root.co.uk!gwc) UniSoft Limited, London, England. Tel: +44 71 729 3773 Fax: +44 71 729 3273
les@chinet.chi.il.us (Leslie Mikesell) (06/05/91)
In article <2729@root44.co.uk> gwc@root.co.uk (Geoff Clare) writes: >Although this works on most if not all current UNIX systems, it's not >required by POSIX, so applications using this method may not work >on some future systems. For maximum portability to current and >future systems, I recommend using the following method to open both >sides of a FIFO to do blocking I/O: > > fd_rd = open("FIFO", O_RDONLY|O_NONBLOCK); > fd_wr = open("FIFO", O_WRONLY); > flags = fcntl(fd_rd, F_GETFL); > fcntl(fd_rd, F_SETFL, flags & ~O_NONBLOCK); Is it required to work when the process opens with one fd for reading and a different one for writing? I do that in shell scripts to make them block when no one else is writing to the FIFO: ---simple shell script server--- setup code... while read CMD P1 P2 P3 P4 P5 P6 do case "$CMD" in STOP) exit 0 ;; whatever else... esac done <FIFO 4>FIFO I just start one of these in the background to schedule jobs and other scripts periodically echo commands to it. IMHO FIFO's would be pretty useless if you couldn't get reasonable blocking to happen from a shell script. I also use the non-blocking mode that happens after the first writer closes in some other scripts. The setup is similar except for the 4>FIFO and a calling script always writes a dummy command after starting the daemon script in the background. In this case the daemon program has something to do in the body of the loop and only checks periodically for controlling commands. If nothing has been written since the last time around the read returns EOF (nothing) and the loop continues. Is this behaviour portable? Les Mikesell les@chinet.chi.il.us