(Merge 3.3) Issue #20113: os.readv() and os.writev() now raise an OSError

exception on error instead of returning -1.
This commit is contained in:
Victor Stinner 2014-01-08 15:26:12 +01:00
commit 149e540adf
4 changed files with 36 additions and 10 deletions

View File

@ -1267,6 +1267,11 @@ class TestInvalidFD(unittest.TestCase):
def test_read(self): def test_read(self):
self.check(os.read, 1) self.check(os.read, 1)
@unittest.skipUnless(hasattr(os, 'readv'), 'test needs os.readv()')
def test_readv(self):
buf = bytearray(10)
self.check(os.readv, [buf])
@unittest.skipUnless(hasattr(os, 'tcsetpgrp'), 'test needs os.tcsetpgrp()') @unittest.skipUnless(hasattr(os, 'tcsetpgrp'), 'test needs os.tcsetpgrp()')
def test_tcsetpgrpt(self): def test_tcsetpgrpt(self):
self.check(os.tcsetpgrp, 0) self.check(os.tcsetpgrp, 0)
@ -1275,6 +1280,10 @@ class TestInvalidFD(unittest.TestCase):
def test_write(self): def test_write(self):
self.check(os.write, b" ") self.check(os.write, b" ")
@unittest.skipUnless(hasattr(os, 'writev'), 'test needs os.writev()')
def test_writev(self):
self.check(os.writev, [b'abc'])
class LinkTests(unittest.TestCase): class LinkTests(unittest.TestCase):
def setUp(self): def setUp(self):

View File

@ -283,9 +283,14 @@ class PosixTester(unittest.TestCase):
def test_writev(self): def test_writev(self):
fd = os.open(support.TESTFN, os.O_RDWR | os.O_CREAT) fd = os.open(support.TESTFN, os.O_RDWR | os.O_CREAT)
try: try:
os.writev(fd, (b'test1', b'tt2', b't3')) n = os.writev(fd, (b'test1', b'tt2', b't3'))
self.assertEqual(n, 10)
os.lseek(fd, 0, os.SEEK_SET) os.lseek(fd, 0, os.SEEK_SET)
self.assertEqual(b'test1tt2t3', posix.read(fd, 10)) self.assertEqual(b'test1tt2t3', posix.read(fd, 10))
# Issue #20113: empty list of buffers should not crash
self.assertEqual(posix.writev(fd, []), 0)
finally: finally:
os.close(fd) os.close(fd)
@ -298,6 +303,9 @@ class PosixTester(unittest.TestCase):
buf = [bytearray(i) for i in [5, 3, 2]] buf = [bytearray(i) for i in [5, 3, 2]]
self.assertEqual(posix.readv(fd, buf), 10) self.assertEqual(posix.readv(fd, buf), 10)
self.assertEqual([b'test1', b'tt2', b't3'], [bytes(i) for i in buf]) self.assertEqual([b'test1', b'tt2', b't3'], [bytes(i) for i in buf])
# Issue #20113: empty list of buffers should not crash
self.assertEqual(posix.readv(fd, []), 0)
finally: finally:
os.close(fd) os.close(fd)

View File

@ -18,6 +18,9 @@ Core and Builtins
Library Library
------- -------
- Issue #20113: os.readv() and os.writev() now raise an OSError exception on
error instead of returning -1.
- Issue #19719: Make importlib.abc.MetaPathFinder.find_module(), - Issue #19719: Make importlib.abc.MetaPathFinder.find_module(),
PathEntryFinder.find_loader(), and Loader.load_module() use PEP 451 APIs to PathEntryFinder.find_loader(), and Loader.load_module() use PEP 451 APIs to
help with backwards-compatibility. help with backwards-compatibility.

View File

@ -8011,14 +8011,14 @@ iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type)
*iov = PyMem_New(struct iovec, cnt); *iov = PyMem_New(struct iovec, cnt);
if (*iov == NULL) { if (*iov == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
return total; return -1;
} }
*buf = PyMem_New(Py_buffer, cnt); *buf = PyMem_New(Py_buffer, cnt);
if (*buf == NULL) { if (*buf == NULL) {
PyMem_Del(*iov); PyMem_Del(*iov);
PyErr_NoMemory(); PyErr_NoMemory();
return total; return -1;
} }
for (i = 0; i < cnt; i++) { for (i = 0; i < cnt; i++) {
@ -8043,7 +8043,7 @@ fail:
PyBuffer_Release(&(*buf)[j]); PyBuffer_Release(&(*buf)[j]);
} }
PyMem_Del(*buf); PyMem_Del(*buf);
return 0; return -1;
} }
static void static void
@ -8083,7 +8083,7 @@ posix_readv(PyObject *self, PyObject *args)
} }
cnt = PySequence_Size(seq); cnt = PySequence_Size(seq);
if (!iov_setup(&iov, &buf, seq, cnt, PyBUF_WRITABLE)) if (iov_setup(&iov, &buf, seq, cnt, PyBUF_WRITABLE) < 0)
return NULL; return NULL;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
@ -8091,6 +8091,9 @@ posix_readv(PyObject *self, PyObject *args)
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
iov_cleanup(iov, buf, cnt); iov_cleanup(iov, buf, cnt);
if (n < 0)
return posix_error();
return PyLong_FromSsize_t(n); return PyLong_FromSsize_t(n);
} }
#endif #endif
@ -8216,8 +8219,8 @@ posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
Py_ssize_t i = 0; /* Avoid uninitialized warning */ Py_ssize_t i = 0; /* Avoid uninitialized warning */
sf.hdr_cnt = PySequence_Size(headers); sf.hdr_cnt = PySequence_Size(headers);
if (sf.hdr_cnt > 0 && if (sf.hdr_cnt > 0 &&
!(i = iov_setup(&(sf.headers), &hbuf, (i = iov_setup(&(sf.headers), &hbuf,
headers, sf.hdr_cnt, PyBUF_SIMPLE))) headers, sf.hdr_cnt, PyBUF_SIMPLE)) < 0)
return NULL; return NULL;
#ifdef __APPLE__ #ifdef __APPLE__
sbytes += i; sbytes += i;
@ -8233,8 +8236,8 @@ posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
Py_ssize_t i = 0; /* Avoid uninitialized warning */ Py_ssize_t i = 0; /* Avoid uninitialized warning */
sf.trl_cnt = PySequence_Size(trailers); sf.trl_cnt = PySequence_Size(trailers);
if (sf.trl_cnt > 0 && if (sf.trl_cnt > 0 &&
!(i = iov_setup(&(sf.trailers), &tbuf, (i = iov_setup(&(sf.trailers), &tbuf,
trailers, sf.trl_cnt, PyBUF_SIMPLE))) trailers, sf.trl_cnt, PyBUF_SIMPLE)) < 0)
return NULL; return NULL;
#ifdef __APPLE__ #ifdef __APPLE__
sbytes += i; sbytes += i;
@ -8475,7 +8478,7 @@ posix_writev(PyObject *self, PyObject *args)
} }
cnt = PySequence_Size(seq); cnt = PySequence_Size(seq);
if (!iov_setup(&iov, &buf, seq, cnt, PyBUF_SIMPLE)) { if (iov_setup(&iov, &buf, seq, cnt, PyBUF_SIMPLE) < 0) {
return NULL; return NULL;
} }
@ -8484,6 +8487,9 @@ posix_writev(PyObject *self, PyObject *args)
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
iov_cleanup(iov, buf, cnt); iov_cleanup(iov, buf, cnt);
if (res < 0)
return posix_error();
return PyLong_FromSsize_t(res); return PyLong_FromSsize_t(res);
} }
#endif #endif