Skip to content

gh-154324: Fix os.sendfile() error reporting on illumos#154327

Open
serhiy-storchaka wants to merge 2 commits into
python:mainfrom
serhiy-storchaka:illumos-sendfile-errors
Open

gh-154324: Fix os.sendfile() error reporting on illumos#154327
serhiy-storchaka wants to merge 2 commits into
python:mainfrom
serhiy-storchaka:illumos-sendfile-errors

Conversation

@serhiy-storchaka

@serhiy-storchaka serhiy-storchaka commented Jul 21, 2026

Copy link
Copy Markdown
Member

illumos sendfile(3EXT) returns the number of transferred bytes by adding it to *off without initializing it, so the offset cannot be used to detect a partial write when the call fails before writing any data, and errors were reported as successful transfers.

Use sendfilev(3EXT) instead, which reports the number of transferred bytes in an explicit out parameter.

illumos sendfile(3EXT) returns the number of transferred bytes by adding
it to the offset without initializing it, so the offset cannot be used to
detect a partial write.  Use sendfilev(3EXT), which reports the number of
transferred bytes in an explicit out parameter.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@serhiy-storchaka serhiy-storchaka added needs backport to 3.13 bugs and security fixes needs backport to 3.14 bugs and security fixes needs backport to 3.15 pre-release feature fixes, bugs and security fixes labels Jul 21, 2026
@serhiy-storchaka

Copy link
Copy Markdown
Member Author

@kulikjak, could you please look at this and verify if it works on real Solaris?

@kulikjak

Copy link
Copy Markdown
Contributor

This one is Illumos specific - sendfile correctly returns zero in this case on Solaris.

$> LD_LIBRARY_PATH=./build/sparcv9/ ./build/sparcv9/python
Python 3.16.0a0 (main, Jul 22 2026, 10:55:24) [GCC 15.2.0] on sunos5
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> fd = os.open("file", os.O_RDONLY)   # not writable, sendfile() fails with EBADF
>>> os.sendfile(fd, fd, 0, 65536)
0

sendfile on Illumos does work differently than on Oracle Solaris - the "sendfile raises EINVAL rather than returning 0" part applies to both, but the "On illumos specifically sendfile() may perform a partial write ..." part (added with #23154) does not apply to us. (We considered hiding it behind Illumos specific #ifdef, but gcc does not differentiate between these two platforms, so we would need some detection in configure, and since it works on both (just does nothing on Oracle Solaris), we kept it like this).

I again tested it with your change on our end, and all tests still pass.

I never tried using sendfilev - maybe it won't need the first part either? I will test that.

@serhiy-storchaka

Copy link
Copy Markdown
Member Author

I tested sendfilev() at and past EOF on illumos, and it still needs the first part:

file size 10
offset=0    count=4096   sendfilev ret=-1 EINVAL xferred=10
offset=10   count=4096   sendfilev ret=-1 EINVAL xferred=0
offset=110  count=4096   sendfilev ret=-1 EINVAL xferred=0

At offset >= size it fails with EINVAL and reports nothing transferred, the same as sendfile().

The two parts are complementary: the fstat() check turns EOF into 0, and xferred makes the first line report 10 instead of an error.

Oracle Solaris is not affected: its sendfile() reports the number of
transferred bytes correctly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@serhiy-storchaka serhiy-storchaka changed the title gh-154324: Fix os.sendfile() error reporting on Solaris gh-154324: Fix os.sendfile() error reporting on illumos Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting core review needs backport to 3.13 bugs and security fixes needs backport to 3.14 bugs and security fixes needs backport to 3.15 pre-release feature fixes, bugs and security fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants