tags:

views:

715

answers:

4

If I am counting on my write() system call to write say e.g., 100 bytes, I always put that write() call in a loop that checks to see if the length that gets returned is what I expected to send and, if not, it bumps the buffer pointer and decreases the length by the amount that was written.

So once again I just did this, but now that there's StackOverflow, I can ask you all if people know when my writes will write ALL that I ask for versus give me back a partial write?

Additional comments: X-Istence's reply reminded me that I should have noted that the file descriptor was blocking (i.e., not non-blocking). I think he is suggesting that the only way a write() on a blocking file descriptor will not write all the specified data is when the write() is interrupted by a signal. This seems to make at least intuitive sense to me...

A: 

Writes shouldn't have any reason to ever write a partial buffer afaik. Possible reasons I could think of for a partial write is if you run out of disk space, you're writing past the end of a block device, or if you're writing to a char device / some other sort of device.

However, the plan to retry writes blindly is probably not such a good one - check errno to see whether you should be retrying first.

Paul Betts
You can't rely on errnon since it is not an error, Artyom answer is the way to go. Giving advice for the usual case is just wrong, char device, fifo, socket etc ... are not so unusual anyway, and you don't know where or when the code will be reused.
shodanex
That's exactly what I said - check the errno to see whether you should retry
Paul Betts
But a partial write is not an error so there is nothing to check
shodanex
A: 

In networking contexts, the books (Stevens "UNIX Network Programming, Vol 1, 3rd Edn", for example) discuss handling short writes and doing as you do.

Normally, if you're writing to disk, your writes will complete. If they don't, there was a shortage of disk space. You can try again; you might be lucky and someone may have removed a (preferably) big file that was hogging space. But most likely, the write will fail again. You probably want to keep a track of the number of iterations - and not continue trying if you get nowhere.

Jonathan Leffler
You forgot to mention that a call may be interrupted by a signal which would cause write to also return before it had written everything to disk.
X-Istence
Good point - yes, I did forget to mention that. On some systems, for some system calls, the system call may be restarted, or resumed, instead of returning with EINTR.
Jonathan Leffler
+4  A: 

write may return partial write especially using operations on sockets or if internal buffers full. So good way is to do following:

while(size > 0 && (res=write(fd,buff,size))!=size) {
    if(res<0 && errno==EINTR) 
       continue;
    if(res < 0) {
        // real error processing
        break;
    }
    size=-res;
    buf+=res;
}

Never relay on what usually happens...

Note: in case of full disk you would get ENOSPC not partial write.

Artyom
+2  A: 

You need to check errno to see if your call got interrupted, or why write() returned early, and why it only wrote a certain number of bytes.

From man 2 write

When using non-blocking I/O on objects such as sockets that are subject to flow control, write() and writev() may write fewer bytes than requested; the return value must be noted, and the remainder of the operation should be retried when possible.

Basically, unless you are writing to a non-blocking socket, the only other time this will happen is if you get interrupted by a signal.

[EINTR] A signal interrupted the write before it could be completed.

See the Errors section in the man page for more information on what can be returned, and when it will be returned. From there you need to figure out if the error is severe enough to log an error and quit, or if you can continue the operation at hand!

This is all discussed in the book: Advanced Unix Programming by Marc J. Rochkind, I have written countless programs with the help of this book, and would suggest it while programming for a UNIX like OS.

X-Istence