One thread writes to a file (or even delete it), another one calls sendfile() for that file simultaneously for overlapping positions.
What is the expected behaviour here?
Also, If my understanding is correct, sendfile call will just add a record to socket (file description, position, length) and return to caller. (no copy to socket’s buffer yet?), so even sendfile() returns before modification to file, OS depends on file existence until file is sent completely.
So what is the result of any modification until file is sent?
Advertisement
Answer
The expected behavior is that the result is unpredictable. sendfile()
is not atomic, it’s effectively equivalent to writing your own loop that calls read()
from the file descriptor and write()
on the socket descriptor. If some other process writes to the file while this is going on, you’ll get a mix of the old and new contents. Think of it mainly as a convenience function, although it also should be significantly more efficient since it doesn’t require multiple system calls, and can copy directly between the file buffer and the socket buffer, rather than copying back and forth between application buffers. Because of this the window of vulnerability should be smaller than doing the read/write
loop, but it’s still there.
To avoid this problem, you should use file locking between the process(es) doing the writing and the one calling sendfile()
. So the sequence should be:
lock the file call sendfile() unlock the file
and the writing process should do:
lock the file write to the file unlock the file
EDIT:
Actually, it looks like it isn’t this simple, because sendfile()
links the socket buffer to the file buffer cache, rather than copying it in the kernel. Since sendfile()
doesn’t wait for the data to be sent, modifying the file after it returns could still affect what gets sent. You need to check that the data has all been received with application-layer acknowledgements. See Minimizing copies when writing large data to a socket for an excerpt from an article that explains these details.