feat: invoke native sendfile(2) on macOS#4043
Merged
Merged
Conversation
Darwin ships a BSD-style sendfile(2) syscall, but the dispatch in crates/fast_io/src/sendfile.rs only branched on Linux and fell through to a read/write loop on every other unix target. The macOS fast_io audit at docs/audits/macos-fastio-fallback.md flagged this as one of two unshipped wins identified during the post-merge review of PR #4008. This change adds a target_os = "macos" arm in send_file_to_fd and send_file_to_fd_with_policy that calls libc::sendfile with the Darwin signature: int sendfile(int fd, int s, off_t offset, off_t *len, struct sf_hdtr *hdtr, int flags); The implementation handles the in/out `len` parameter (bytes to send -> bytes actually sent), treats a return of 0 as success, and preserves the "transfer from the current file position" contract by querying the source offset with lseek(SEEK_CUR) and advancing the position with lseek(SEEK_SET) after the transfer. Partial sends on EAGAIN/EINTR are reported as forward progress so the socket peer always sees a consistent prefix. Non-socket destinations (pipes, regular files) fail with ENOTSOCK; the dispatch transparently falls back to the buffered read/write loop in that case, matching the behaviour Linux already had for non-sendfile-capable targets. Tests gated to target_os = "macos" exercise the new path through a SOCK_STREAM socketpair (native sendfile fast path), the public dispatch entry point, and a pipe destination that must fall back to read/write. Refs #2152.
oferchen
added a commit
that referenced
this pull request
May 18, 2026
Darwin ships a BSD-style sendfile(2) syscall, but the dispatch in crates/fast_io/src/sendfile.rs only branched on Linux and fell through to a read/write loop on every other unix target. The macOS fast_io audit at docs/audits/macos-fastio-fallback.md flagged this as one of two unshipped wins identified during the post-merge review of PR #4008. This change adds a target_os = "macos" arm in send_file_to_fd and send_file_to_fd_with_policy that calls libc::sendfile with the Darwin signature: int sendfile(int fd, int s, off_t offset, off_t *len, struct sf_hdtr *hdtr, int flags); The implementation handles the in/out `len` parameter (bytes to send -> bytes actually sent), treats a return of 0 as success, and preserves the "transfer from the current file position" contract by querying the source offset with lseek(SEEK_CUR) and advancing the position with lseek(SEEK_SET) after the transfer. Partial sends on EAGAIN/EINTR are reported as forward progress so the socket peer always sees a consistent prefix. Non-socket destinations (pipes, regular files) fail with ENOTSOCK; the dispatch transparently falls back to the buffered read/write loop in that case, matching the behaviour Linux already had for non-sendfile-capable targets. Tests gated to target_os = "macos" exercise the new path through a SOCK_STREAM socketpair (native sendfile fast path), the public dispatch entry point, and a pipe destination that must fall back to read/write. Refs #2152.
oferchen
added a commit
that referenced
this pull request
May 18, 2026
Darwin ships a BSD-style sendfile(2) syscall, but the dispatch in crates/fast_io/src/sendfile.rs only branched on Linux and fell through to a read/write loop on every other unix target. The macOS fast_io audit at docs/audits/macos-fastio-fallback.md flagged this as one of two unshipped wins identified during the post-merge review of PR #4008. This change adds a target_os = "macos" arm in send_file_to_fd and send_file_to_fd_with_policy that calls libc::sendfile with the Darwin signature: int sendfile(int fd, int s, off_t offset, off_t *len, struct sf_hdtr *hdtr, int flags); The implementation handles the in/out `len` parameter (bytes to send -> bytes actually sent), treats a return of 0 as success, and preserves the "transfer from the current file position" contract by querying the source offset with lseek(SEEK_CUR) and advancing the position with lseek(SEEK_SET) after the transfer. Partial sends on EAGAIN/EINTR are reported as forward progress so the socket peer always sees a consistent prefix. Non-socket destinations (pipes, regular files) fail with ENOTSOCK; the dispatch transparently falls back to the buffered read/write loop in that case, matching the behaviour Linux already had for non-sendfile-capable targets. Tests gated to target_os = "macos" exercise the new path through a SOCK_STREAM socketpair (native sendfile fast path), the public dispatch entry point, and a pipe destination that must fall back to read/write. Refs #2152.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
target_os = \"macos\"arm tosend_file_to_fdandsend_file_to_fd_with_policyincrates/fast_io/src/sendfile.rsso file-to-socket transfers use Darwin's nativesendfile(2)instead of falling through to a bufferedread/writeloop.int sendfile(int fd, int s, off_t offset, off_t *len, struct sf_hdtr *hdtr, int flags)). The newtry_sendfile_macoshandles the in/outlenparameter, treats a return of0as success, retries / records forward progress onEAGAIN/EINTR, and preserves the "transfer from the current file position" contract by querying the source offset withlseek(SEEK_CUR)and advancing it withlseek(SEEK_SET)after the transfer.ENOTSOCKand fall back to the existing buffered loop, matching the behaviour Linux already had on non-sendfile-capable targets.This is the macOS sendfile gap called out in
docs/audits/macos-fastio-fallback.md(section 3.5 + section 5 item 2), produced as part of PR #4008. The unsafe FFI stays insidefast_io, the only crate permitted to wrap platform syscalls.Refs #2152.
Test plan
cargo fmt --all -- --checkcargo clippy --workspace --all-targets --all-features --no-deps -- -D warningscargo nextest run -p fast_io --all-featureson macOS exercises the three new tests:test_send_file_to_fd_socketpair_macos- callstry_sendfile_macosdirectly against aSOCK_STREAMsocketpair and asserts the bytes match.test_send_file_to_fd_dispatch_uses_native_macos- drives the publicsend_file_to_fdagainst aSOCK_STREAMsocketpair end-to-end.test_send_file_to_fd_macos_non_socket_falls_back- sends to a pipe; Darwin'ssendfilerejects it withENOTSOCKand the dispatch must fall back tocopy_via_fd_writewhile still delivering the bytes.#[cfg(target_os = \"macos\")]only).