Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

POSIX partial write()

As is described in SUSv4 or POSIX.1-2008
http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html#tag_16_685_08
The write() call may return a value less than nbytes if write()ing to a NONBLOCK pipe/FIFO. Thus, it's necessary to check the return value and write() the rest of the buffer in a loop demonstrated below:

while (bytes_to_write > 0) {
    select(...);                 // Or poll()
    retv = write(...);
    if (retv < 0)
        ...                      // Error
    bytes_to_write -= retv;
}

The standard says nothing about regular files, special files (aka. devices) and sockets, especially stream-based sockets (TCP sockets and UNIX Domain ones, for example).

Then, I have the following two questions:

  • Will partial write() (or partial send()) possibly occur on regular files (or sockets with O_NONBLOCK unset) ?
  • How about writev() and sendmsg() on NONBLOCK sockets? This is very important, since dealing with partially written vector (struct iovec []) is a bit of trouble.

Sorry for broken English.

like image 504
Lv Zheng Avatar asked Jul 31 '15 03:07

Lv Zheng


People also ask

What does write () do?

The write() function attempts to write nbyte bytes from the buffer pointed to by buf to the file associated with the open file descriptor, fildes. If nbyte is 0, write() will return 0 and have no other results if the file is a regular file; otherwise, the results are unspecified.

What is partial write?

Partial writes are rare occurrences. One way it could happen is if you attempt to write 4 KiB of data to a file system that has only 1 KiB of space left. Other ways are similarly arcane. – Jonathan Leffler. Nov 25, 2021 at 14:48.

What is the return value of write?

The write function returns the number of bytes successfully written into the file, which may at times be less than the specified nbytes. It returns -1 if an exceptional condition is encountered, see section on errors below.

Is write a blocking call?

Succinctly, both read() and write() can be blocking or non-blocking, depending on circumstances.


1 Answers

Ok. Since the standard does't provide any guarantee, we can't assume full write()s.

I Googled partial writev and got an answer:

http://developerweb.net/viewtopic.php?id=4154

Yes, I've seen that behavior before as well (though, with sendmsg() and its iovecs)... And, actually, no it's NOT incorrect/unexpected behavior... Both read()/recv() and write()/send() (and all permutations of the I/O funcs) can return short reads/writes, and all sockets code needs to be prepared to deal with that... It doesn't matter if they're blocking or non-blocking mode sockets, either... All that controls is what happens when the buffer is totally empty (in the case of input) or totally full (in the case of output)... But, when the send buffer isn't quite full, any write to it (via a blocking or non-blocking socket) of more than the amount of free space left will write as much as it can, and then return the short write count... And, you are expected to handle calling it again, to send the remaining amount... With normal write()/send(), it's easy to do, but with writev()/sendmsg() iovecs, it does become tricky to handle, and a real pain... But, you still MUST do it

writev_all() can't be avoided.

Thanks.

like image 51
Lv Zheng Avatar answered Oct 03 '22 15:10

Lv Zheng