(original) (raw)

diff --git a/Lib/socket.py b/Lib/socket.py --- a/Lib/socket.py +++ b/Lib/socket.py @@ -253,17 +253,17 @@ class socket(_socket.socket): self._check_sendfile_params(file, offset, count) sockno = self.fileno() try: fileno = file.fileno() except (AttributeError, io.UnsupportedOperation) as err: raise _GiveupOnSendfile(err) # not a regular file try: fsize = os.fstat(fileno).st_size - except OSError: + except OSError as err: raise _GiveupOnSendfile(err) # not a regular file if not fsize: return 0 # empty file blocksize = fsize if not count else count timeout = self.gettimeout() if timeout == 0: raise ValueError("non-blocking sockets are not supported") diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1,9 +1,10 @@ import unittest +import unittest.mock as mock from test import support import errno import io import itertools import socket import select import tempfile @@ -1442,16 +1443,29 @@ class GeneralModuleTests(unittest.TestCa # type and populates the socket object. # # On Windows this trick won't work, so the test is skipped. fd, _ = tempfile.mkstemp() with socket.socket(family=42424, type=13331, fileno=fd) as s: self.assertEqual(s.family, 42424) self.assertEqual(s.type, 13331) + @mock.patch('socket.os.fstat', side_effect=OSError) + @unittest.skipUnless(hasattr(os, 'sendfile'), 'test needs os.sendfile()') + def test_unbound_local_error_in__sendfile_use_sendfile(self, mock_fstat): + # see issue XXXX for details + with open(support.TESTFN, 'wb') as file: + file.write(b'foo') + self.addCleanup(support.unlink, support.TESTFN) + with socket.socket() as sock, open(support.TESTFN, 'rb') as file: + self.assertRaises(socket._GiveupOnSendfile, + sock._sendfile_use_sendfile, file) + self.assertTrue(mock_fstat.called) + + @unittest.skipUnless(HAVE_SOCKET_CAN, 'SocketCan required for this test.') class BasicCANTest(unittest.TestCase): def testCrucialConstants(self): socket.AF_CAN socket.PF_CAN socket.CAN_RAW