Flash
Flash

Reputation: 16743

Is it possible to have read not block, but write block for pipes?

man 2 select states the following under BUGS:

Under Linux, select() may report a socket file descriptor as "ready for reading", while nevertheless a subsequent read blocks. This could for example happen when data has arrived but upon examination has wrong checksum and is discarded. There may be other circumstances in which a file descriptor is spuriously reported as ready. Thus it may be safer to use O_NONBLOCK on sockets that should not block.

Thus, my read calls need to not block and therefore I have marked my pipe file descriptors O_NONBLOCK. However, I want write calls to block until data is written to the pipe.

Is it possible to have write block when writing data to the pipe, but have read not block the reading end? Is it legal for instance to call fcntl on one end only after the pipe has been created, since read and write ends have separate file descriptors?

Upvotes: 5

Views: 1230

Answers (1)

Marian
Marian

Reputation: 7482

You surely can remove O_NONBLOCK flag before each write with fcntl and put it back after write completes. However, it seems better to keep the socket non-blocking all the time and to put write into a loop until it finishes. In order not to overload the CPU, put a select which will block the process until the socket is ready for write.

So, the writing code will look like:

int blockingWriteOnNonBlockingFd(int fd, char *buf, int size) {
  fd_set wset, w;
  int    n, r;
  FD_ZERO(&wset);
  FD_SET(fd, &wset);
  n = 0;
  while (n < size) {
    w = wset;
    select(fd+1, NULL, &w, NULL, NULL);
    r = write(fd, buf+n, size-n);
    if (r <= 0) {
       if (r<0 && (errno == EWOULDBLOCK || errno == EAGAIN)) r = 0;
       else { /* broken connection */ break; }
    }
    n += r;
  }
  return(n);
}

Upvotes: 3

Related Questions