-
Notifications
You must be signed in to change notification settings - Fork 17.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
syscall: Sendfile needs documentation #64044
Comments
(CC @panjf2000) |
I also don't think it modifies Differences between FreeBSD and Linux sendfile: /*
* Differences between FreeBSD and Linux sendfile:
* - Linux doesn't send anything when count is 0 (FreeBSD uses 0 to
* mean send the whole file.) In linux_sendfile given fds are still
* checked for validity when the count is 0.
* - Linux can send to any fd whereas FreeBSD only supports sockets.
* The same restriction follows for linux_sendfile.
* - Linux doesn't have an equivalent for FreeBSD's flags and sf_hdtr.
* - Linux takes an offset pointer and updates it to the read location.
* FreeBSD takes in an offset and a 'bytes read' parameter which is
* only filled if it isn't NULL. We use this parameter to update the
* offset pointer if it exists.
* - Linux sendfile returns bytes read on success while FreeBSD
* returns 0. We use the 'bytes read' parameter to get this value.
*/ |
Thank you for bringing this up. @bcmills As the Linux man pages stated, As for the scenario of partial write, Another implementation detail worth mentioning is that |
Change https://go.dev/cl/546295 mentions this issue: |
Change https://go.dev/cl/537275 mentions this issue: |
…he code readability for SendFile There were a bit too many conditional branches in the old code, resulting in a poor readability. It could be more concise by reducing and consolidating some of the conditions. Furthermore, how we've determined whether or not the data transimission was handled by sendfile(2) seems inappropriate, because it marked the operation as unhandled whenever any non-retryable error occurs from calling sendfile(2), it doesn't look like a right approach, at least this is an inconsistent behavior with what we've done in Splice. Related to #64044 Change-Id: Ieb65e0879a8841654d0e64a1263a4e43179df1ba Reviewed-on: https://go-review.googlesource.com/c/go/+/537275 TryBot-Result: Gopher Robot <gobot@golang.org> Commit-Queue: Ian Lance Taylor <iant@golang.org> Run-TryBot: Andy Pan <panjf2000@gmail.com> Auto-Submit: Ian Lance Taylor <iant@golang.org> Reviewed-by: Damien Neil <dneil@google.com> Reviewed-by: Bryan Mills <bcmills@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
As of Go 1.21, the
syscall.Sendfile
function has no documentation.For many functions in the
syscall
package, we assume POSIX semantics in the absence of explicit documentation. However,sendfile
is not defined by POSIX, and its semantics vary significantly among platforms.Notably:
On Linux, “
sendfile()
will transfer at most 0x7ffff000 (2,147,479,552) bytes, returning the number of bytes actually transferred”. FreeBSD, macOS, and Solaris do not document any such restriction.The reporting of the actual number of bytes transferred varies by platform.
sendfile()
may send fewer bytes than requested” only “[w]hen using a socket marked for non-blocking I/O”. In that case, it sets thesbytes
out-parameter to indicate then number of bytes written, returns -1, and sets errno toEAGAIN
.sendfile()
may write fewer bytes than requested”, but does not specify what happens to theoffset
parameter or the input file's offset on error.sendfile()
may still write some data before encountering an error and returning-1
. When that occurs,off
is updated to point to the byte that follows the last byte copied and should be compared with its value before callingsendfile()
to determine how much data was sent.”It appears that the return-value from Go's
syscall.Sendfile
on FreeBSD and macOS always reports the*sbytes
(a.k.alen
) out-parameter, which is always nonnegative. On Linux and Solaris, it reports the return value from the call, which is -1 on error.The effect on the offset of the input file varies by platform.
offset
parameter is null, “data will be read fromin_fd
starting at the file offset, and the file offset will be updated by the call.”sendfile()
function does not modify the current file pointer ofin_fd
, but does modify the file pointer forout_fd
if it is a regular file.” It does not document any particular behavior if theoff
argument is null, but its error behavior seems to imply than a non-null offset pointer should always be used.fd
is modified by the call. (I'm guessing that it's not, though.)The allowed output descriptors vary by platform.
AF_INET
orAF_INET6
socket ofSOCK_STREAM
type”.In addition, on Solaris and Illumos it appears that
EAGAIN
can be returned for reasons other than full send buffers — it can also occur due to file or record locking on the input or output file.Given these variations, it seems to me that the semantics and usage of the Go syscall wrapper should be documented — especially given that the signature of Go's
syscall.Sendfile
on FreeBSD and macOS doesn't match the signature of the corresponding system C function.References:
The text was updated successfully, but these errors were encountered: