Avoiding blocking writes on FIFOs - Unix

This is a discussion on Avoiding blocking writes on FIFOs - Unix ; Hello everyone, I am trying to avoid a blocking write(), by using appropriate mechanisms to tell me if things can block. mknod("/tmp/foo", S_IFIFO, S_IRUSR | S_IWUSR); int fd = open("/tmp/foo", O_WRONLY); struct pollfd { .fd = fd, .events = POLLOUT, ...

+ Reply to Thread
Results 1 to 3 of 3

Thread: Avoiding blocking writes on FIFOs

  1. Avoiding blocking writes on FIFOs

    Hello everyone,


    I am trying to avoid a blocking write(), by using appropriate mechanisms
    to tell me if things can block.

    mknod("/tmp/foo", S_IFIFO, S_IRUSR | S_IWUSR);
    int fd = open("/tmp/foo", O_WRONLY);
    struct pollfd {
    .fd = fd,
    .events = POLLOUT,
    } pfd;
    poll(&pfd, 1, 0);
    if (pfd.revents & POLLOUT)
    write(fd, some_buffer, some_length);

    You can see that I am specifically working with a FIFO, not a file and
    not a socket. This is an interesting situation because unlike a socket,
    a write() on a pipe will block if some_length is "too big", instead of
    returning a size less than some_length.
    This raises the question how one is going to figure out how many bytes
    the pipe allows before it starts to block. While writing this post, I
    figured that I may have to open the FIFO in O_NONBLOCK mode to make
    write() return less than some_length.
    Is this indeed the recommended way to go?


    Jan
    --

  2. Re: Avoiding blocking writes on FIFOs

    Jan Engelhardt wrote:

    > Hello everyone,


    Hi

    > I am trying to avoid a blocking write(), by using appropriate mechanisms
    > to tell me if things can block.
    >
    > mknod("/tmp/foo", S_IFIFO, S_IRUSR | S_IWUSR);
    > int fd = open("/tmp/foo", O_WRONLY);
    > struct pollfd {
    > .fd = fd,
    > .events = POLLOUT,
    > } pfd;
    > poll(&pfd, 1, 0);
    > if (pfd.revents & POLLOUT)


    This is not entirely safe - the condition might succeed even if the write
    turns out to be impossible.

    > write(fd, some_buffer, some_length);
    >
    > You can see that I am specifically working with a FIFO, not a file and
    > not a socket. This is an interesting situation because unlike a socket,
    > a write() on a pipe will block if some_length is "too big", instead of
    > returning a size less than some_length.


    Generally yes, but you cannot count on that. For example, if you get a
    signal in fortunate moment, write might return less than some_length.

    > This raises the question how one is going to figure out how many bytes
    > the pipe allows before it starts to block.


    Depends on architecture and the state of the pipe. On linux, i386, it is 64
    KiB - amount of unread data waiting in the pipe.

    But note that writes of less than PIPE_BUF (4K on linux i386, may be as low
    as 512 B on other systems) are atomic, that is, they either fail or return
    some_length. They may still block, though.

    > While writing this post, I
    > figured that I may have to open the FIFO in O_NONBLOCK mode to make
    > write() return less than some_length.
    > Is this indeed the recommended way to go?


    Yes. There are other (more advanced) possibilities, like aio.

    Jiri Palecek

  3. Re: Avoiding blocking writes on FIFOs

    Jan Engelhardt wrote:
    > I am trying to avoid a blocking write(), by using appropriate mechanisms
    > to tell me if things can block.
    >
    > mknod("/tmp/foo", S_IFIFO, S_IRUSR | S_IWUSR);
    > int fd = open("/tmp/foo", O_WRONLY);
    > struct pollfd {
    > .fd = fd,
    > .events = POLLOUT,
    > } pfd;
    > poll(&pfd, 1, 0);
    > if (pfd.revents & POLLOUT)
    > write(fd, some_buffer, some_length);
    >
    > You can see that I am specifically working with a FIFO, not a file and
    > not a socket. This is an interesting situation because unlike a socket,
    > a write() on a pipe will block if some_length is "too big", instead of
    > returning a size less than some_length.


    A socket behaves the same as a FIFO, except if size <= PIPE_BUF, where
    it's all-or-nothing for a FIFO.

    > This raises the question how one is going to figure out how many bytes
    > the pipe allows before it starts to block. While writing this post, I
    > figured that I may have to open the FIFO in O_NONBLOCK mode to make
    > write() return less than some_length.
    > Is this indeed the recommended way to go?


    It's the *only* way to go for select()/poll() plus normal read()/write().

    Note that open(fifo, O_WRONLY | O_NONBLOCK) will fail unless a process
    has the FIFO open for reading. If it suits, you could block on open()
    and subsequently set non-blocking mode with fcntl().

    Alex

+ Reply to Thread