From: Łukasz Langa Date: Wed, 16 Sep 2020 11:52:26 +0000 (+0200) Subject: [3.9] bpo-41687: Fix sendfile implementation to work with Solaris (GH-22040) (GH... X-Git-Tag: v3.9.0rc2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7e356f17e4c91392b6fa45a512efc95923388813;p=thirdparty%2FPython%2Fcpython.git [3.9] bpo-41687: Fix sendfile implementation to work with Solaris (GH-22040) (GH-22273) (cherry picked from commit 8c0be6fd9101746235b63ddfb84106d1e9ca286b) Co-authored-by: Jakub Kulík --- diff --git a/Lib/test/test_asyncio/test_sendfile.py b/Lib/test/test_asyncio/test_sendfile.py index dbce199a9b8e..1b1af08db0a1 100644 --- a/Lib/test/test_asyncio/test_sendfile.py +++ b/Lib/test/test_asyncio/test_sendfile.py @@ -445,6 +445,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 index 000000000000..284f50073570 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-09-01-15-57-51.bpo-41687.m1b1KA.rst @@ -0,0 +1 @@ +Fix implementation of sendfile to be compatible with Solaris. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index ddff28354a7c..39f5f577a828 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -9453,6 +9453,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);