[Python-checkins] bpo-42237: Fix os.sendfile() on illumos (GH-23154)

miss-islington webhook-mailer at python.org
Thu Nov 12 05:14:20 EST 2020


https://github.com/python/cpython/commit/7ae19ef5cf5d4f464588133bd48f81d80ea54aee
commit: 7ae19ef5cf5d4f464588133bd48f81d80ea54aee
branch: 3.9
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: miss-islington <31488909+miss-islington at users.noreply.github.com>
date: 2020-11-12T02:14:03-08:00
summary:

bpo-42237: Fix os.sendfile() on illumos (GH-23154)

(cherry picked from commit fd4ed57674c675e05bd5d577dd5047a333c76c78)

Co-authored-by: Jakub Stasiak <jakub at stasiak.at>

files:
A Misc/NEWS.d/next/Library/2020-11-10-14-27-49.bpo-42237.F363jO.rst
M Modules/posixmodule.c

diff --git a/Misc/NEWS.d/next/Library/2020-11-10-14-27-49.bpo-42237.F363jO.rst b/Misc/NEWS.d/next/Library/2020-11-10-14-27-49.bpo-42237.F363jO.rst
new file mode 100644
index 0000000000000..50cab6e1f11f8
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-11-10-14-27-49.bpo-42237.F363jO.rst
@@ -0,0 +1 @@
+Fix `os.sendfile()` on illumos.
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 01e8bcbd2981a..8e14ffcc856f8 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -9469,11 +9469,26 @@ os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
     if (offset >= st.st_size) {
         return Py_BuildValue("i", 0);
     }
+
+    // On illumos specifically sendfile() may perform a partial write but
+    // return -1/an error (in one confirmed case the destination socket
+    // had a 5 second timeout set and errno was EAGAIN) and it's on the client
+    // code to check if the offset parameter was modified by sendfile().
+    //
+    // We need this variable to track said change.
+    off_t original_offset = offset;
 #endif
 
     do {
         Py_BEGIN_ALLOW_THREADS
         ret = sendfile(out_fd, in_fd, &offset, count);
+#if defined(__sun) && defined(__SVR4)
+        // This handles illumos-specific sendfile() partial write behavior,
+        // see a comment above for more details.
+        if (ret < 0 && offset != original_offset) {
+            ret = offset - original_offset;
+        }
+#endif
         Py_END_ALLOW_THREADS
     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
     if (ret < 0)



More information about the Python-checkins mailing list