Blocking and nonblocking reads

By default, reads to PPS objects are nonblocking; that is, PPS defaults a normal open() to O_NONBLOCK, so that reads made by the client that opened the object don't block. This behavior is atypical for most filesystems. It's done this way so that standard utilities won't hang waiting for a change when they make a read() call on a file.

For example, with the default behavior, you could tar up the entire state of PPS using the standard tar utility. Without this default behavior, however, tar would never make it past the first file opened and read.

Setting PPS to block

Though the PPS default is to open objects for nonblocking reads, the preferred method for querying PPS objects is to use blocking reads. With this method, a read waits until the object or its attributes change, then returns data.

To have reads block, you need to open the object with the ?wait pathname open option, appended as a suffix to the pathname for the object. (For more information on the ?wait option, see Pathname open options.)

For example:
  • to open the PlayList object for the default nonblocking reads, use the pathname:"/pps/media/PlayList"
  • to open the PlayList for blocking reads, use the pathname plus the option: "/pps/media/PlayList?wait"

A typical loop in a subscriber would live in its own thread. For a subscriber that opened the object with the ?wait option, this loop might do the following:

/* Assume that the object was opened with the ?wait option
   No error checking in this example. */
for(;;) {
    read(fd, buf, sizeof(buf)); // Read waits until the object changes.
    process(buf);
}

Clearing O_NONBLOCK

If you have opened an object without the ?wait option and want to change to blocking reads, you can clear the O_NONBLOCK bit, so that the subscriber waits for changes to an object or its attributes.

To clear the bit you can use the fcntl() function. For example:

flags = fcntl(fd, F_GETFL);
flags &= ~O_NONBLOCK;
fcntl(fd, F_SETFL, flags);

Or you can use the ioctl() function:

int i=0;
ioctl(fd,FIONBIO,&i);

After clearing the O_NONBLOCK bit, you can issue a read that waits until the object changes.