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,
...
-
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
--
-
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
-
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