]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Temporary commit of fix to issue #5380 (in order to watch buildbot response)
authorAntoine Pitrou <solipsis@pitrou.net>
Sat, 10 Apr 2010 22:43:05 +0000 (22:43 +0000)
committerAntoine Pitrou <solipsis@pitrou.net>
Sat, 10 Apr 2010 22:43:05 +0000 (22:43 +0000)
Lib/test/test_io.py
Lib/test/test_posix.py
Modules/_io/fileio.c

index 9ffe646ea9fd2b67e8765efd9f1dad69862f0bdc..accf0eb2cc8bb11028d3dd6b0c80094c2c6b06bd 100644 (file)
@@ -2394,6 +2394,47 @@ class MiscIOTest(unittest.TestCase):
         # baseline "io" module.
         self._check_abc_inheritance(io)
 
+    # Issue #5380: reading all available bytes from a pipe or a PTY when
+    # the other end has been closed.
+
+    def check_pipe_func(self, pipe_func, buffered):
+        master_fd, slave_fd = pipe_func()
+        # Simulate a subprocess writing some data to the
+        # slave end of the pipe, and then exiting.
+        data = b'TEST DATA'
+        try:
+            os.write(slave_fd, data)
+        finally:
+            os.close(slave_fd)
+        with self.open(master_fd, "rb", buffering=-1 if buffered else 0) as f:
+            # Request more data than available
+            gotdata = f.read(len(data) + 1)
+            self.assertEqual(gotdata, data)
+            # Trying to read again returns an empty string
+            self.assertEqual(b'', f.read())
+            self.assertEqual(b'', f.read(1))
+
+    def test_pipe_read_buffered(self):
+        if not hasattr(os, 'pipe'):
+            self.skipTest("os.pipe not available")
+        self.check_pipe_func(os.pipe, True)
+
+    def test_pipe_read_raw(self):
+        if not hasattr(os, 'pipe'):
+            self.skipTest("os.pipe not available")
+        self.check_pipe_func(os.pipe, False)
+
+    def test_openpty_read_buffered(self):
+        if not hasattr(os, 'openpty'):
+            self.skipTest("os.openpty not available")
+        self.check_pipe_func(os.openpty, True)
+
+    def test_openpty_read_raw(self):
+        if not hasattr(os, 'openpty'):
+            self.skipTest("os.openpty not available")
+        self.check_pipe_func(os.openpty, False)
+
+
 class CMiscIOTest(MiscIOTest):
     io = io
 
index afeb616ddca7217ec5d54e95121712d87ad3a6d3..3caf82493fdb4428f2b83a095ad30a52369136a3 100644 (file)
@@ -280,11 +280,29 @@ class PosixTester(unittest.TestCase):
         if hasattr(posix, 'strerror'):
             self.assertTrue(posix.strerror(0))
 
+    def check_pipe_func(self, pipe_func):
+        master_fd, slave_fd = pipe_func()
+        try:
+            # Simulate a subprocess writing some data to the
+            # slave end of the pipe, and then exiting.
+            data = b'TEST DATA'
+            try:
+                os.write(slave_fd, data)
+            finally:
+                os.close(slave_fd)
+            # Request more data than available
+            gotdata = os.read(master_fd, len(data) + 1)
+            self.assertEqual(gotdata, data)
+        finally:
+            os.close(master_fd)
+
     def test_pipe(self):
         if hasattr(posix, 'pipe'):
-            reader, writer = posix.pipe()
-            os.close(reader)
-            os.close(writer)
+            self.check_pipe_func(posix.pipe)
+
+    def test_openpty(self):
+        if hasattr(posix, 'openpty'):
+            self.check_pipe_func(posix.openpty)
 
     def test_tempnam(self):
         if hasattr(posix, 'tempnam'):
index ec320f79b977715c04a964fc70e29d8e8cb55d7f..8f174a7edb573cb18b179e97eb47f963ec3eeb77 100644 (file)
@@ -464,6 +464,34 @@ fileio_seekable(fileio *self)
        return PyBool_FromLong((long) self->seekable);
 }
 
+static Py_ssize_t
+internal_read(int fd, void *buf, size_t count)
+{
+       Py_ssize_t n;
+
+       Py_BEGIN_ALLOW_THREADS
+       errno = 0;
+       n = read(fd, buf, count);
+#ifdef EIO
+       /* Issue #5380: when reading past the end of a pipe created by
+          openpty(), EIO can be set.  Make it an EOF instead, so that
+          the normal technique of testing for an empty string can be used.
+        */
+       if (n == -1 && errno == EIO) {
+               if (isatty(fd)) {
+                       n = 0;
+                       errno = 0;
+               }
+               else {
+                       /* isatty() set errno, restore its value */
+                       errno = EIO;
+               }
+       }
+#endif
+       Py_END_ALLOW_THREADS
+       return n;
+}
+
 static PyObject *
 fileio_readinto(fileio *self, PyObject *args)
 {
@@ -478,12 +506,9 @@ fileio_readinto(fileio *self, PyObject *args)
        if (!PyArg_ParseTuple(args, "w*", &pbuf))
                return NULL;
 
-       if (_PyVerify_fd(self->fd)) {
-               Py_BEGIN_ALLOW_THREADS
-               errno = 0;
-               n = read(self->fd, pbuf.buf, pbuf.len);
-               Py_END_ALLOW_THREADS
-       } else
+       if (_PyVerify_fd(self->fd))
+               n = internal_read(self->fd, pbuf.buf, pbuf.len);
+       else
                n = -1;
        PyBuffer_Release(&pbuf);
        if (n < 0) {
@@ -560,12 +585,9 @@ fileio_readall(fileio *self)
                                break;
                        }
                }
-               Py_BEGIN_ALLOW_THREADS
-               errno = 0;
-               n = read(self->fd,
-                        PyBytes_AS_STRING(result) + total,
-                        newsize - total);
-               Py_END_ALLOW_THREADS
+               n = internal_read(self->fd,
+                                 PyBytes_AS_STRING(result) + total,
+                                 newsize - total);
                if (n == 0)
                        break;
                if (n < 0) {
@@ -617,12 +639,9 @@ fileio_read(fileio *self, PyObject *args)
                return NULL;
        ptr = PyBytes_AS_STRING(bytes);
 
-       if (_PyVerify_fd(self->fd)) {
-               Py_BEGIN_ALLOW_THREADS
-               errno = 0;
-               n = read(self->fd, ptr, size);
-               Py_END_ALLOW_THREADS
-       } else
+       if (_PyVerify_fd(self->fd))
+               n = internal_read(self->fd, ptr, size);
+       else
                n = -1;
 
        if (n < 0) {