]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-41687: Fix sendfile implementation to work with Solaris (#22040)
authorJakub Kulík <Kulikjak@gmail.com>
Sat, 5 Sep 2020 19:10:01 +0000 (21:10 +0200)
committerGitHub <noreply@github.com>
Sat, 5 Sep 2020 19:10:01 +0000 (12:10 -0700)
Lib/test/test_asyncio/test_sendfile.py
Misc/NEWS.d/next/Library/2020-09-01-15-57-51.bpo-41687.m1b1KA.rst [new file with mode: 0644]
Modules/posixmodule.c

index a30d9b9b4d9a012e8d26f6b92016b1edc435c8d9..01c698653ec67e5e32bae2c8effda2b31a72def1 100644 (file)
@@ -446,6 +446,12 @@ class SendfileMixin(SendfileBase):
         self.assertEqual(srv_proto.data, self.DATA)
         self.assertEqual(self.file.tell(), len(self.DATA))
 
+    # On Solaris, lowering SO_RCVBUF on a TCP connection after it has been
+    # established has no effect. Due to its age, this bug affects both Oracle
+    # Solaris as well as all other OpenSolaris forks (unless they fixed it
+    # themselves).
+    @unittest.skipIf(sys.platform.startswith('sunos'),
+                     "Doesn't work on Solaris")
     def test_sendfile_close_peer_in_the_middle_of_receiving(self):
         srv_proto, cli_proto = self.prepare_sendfile(close_after=1024)
         with self.assertRaises(ConnectionError):
diff --git a/Misc/NEWS.d/next/Library/2020-09-01-15-57-51.bpo-41687.m1b1KA.rst b/Misc/NEWS.d/next/Library/2020-09-01-15-57-51.bpo-41687.m1b1KA.rst
new file mode 100644 (file)
index 0000000..284f500
--- /dev/null
@@ -0,0 +1 @@
+Fix implementation of sendfile to be compatible with Solaris.
index a6a4b9f012f009a74ed3fa95f065f7476c8f0fd2..00ba7580302bbab6638ae7ad613c36ab665db6e9 100644 (file)
@@ -9518,6 +9518,25 @@ done:
     if (!Py_off_t_converter(offobj, &offset))
         return NULL;
 
+#if defined(__sun) && defined(__SVR4)
+    // On Solaris, sendfile raises EINVAL rather than returning 0
+    // when the offset is equal or bigger than the in_fd size.
+    int res;
+    struct stat st;
+
+    do {
+        Py_BEGIN_ALLOW_THREADS
+        res = fstat(in_fd, &st);
+        Py_END_ALLOW_THREADS
+    } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+    if (ret < 0)
+        return (!async_err) ? posix_error() : NULL;
+
+    if (offset >= st.st_size) {
+        return Py_BuildValue("i", 0);
+    }
+#endif
+
     do {
         Py_BEGIN_ALLOW_THREADS
         ret = sendfile(out_fd, in_fd, &offset, count);