[pypy-issue] Issue #1910: fdopen of pty doesn't match cpython behavior (pypy/pypy)

Buck Evan issues-reply at bitbucket.org
Wed Oct 29 19:11:13 CET 2014


New issue 1910: fdopen of pty doesn't match cpython behavior
https://bitbucket.org/pypy/pypy/issue/1910/fdopen-of-pty-doesnt-match-cpython

Buck Evan:

This is quite similar issue to issue #956, but my script doesn't fail on cpython:

```
$ python2.6 scratch.py
pipe works
pty works

$ python3.4 scratch.py                                                            
pipe works
pty works

$ pypy scratch.py                                                                 
pipe works
Traceback (most recent call last):
  File "app_main.py", line 51, in run_toplevel
  File "scratch.py", line 55, in <module>
    exit(main())
  File "scratch.py", line 51, in main
    print(test_pty())
  File "scratch.py", line 31, in test_pty
    out = pipe_output(read, write)
  File "scratch.py", line 23, in pipe_output
    return fdopen(read).read().replace('\r\n', '\n')
IOError: [Errno 5] Input/output error: '<fdopen>'

$ pypy3 scratch.py
pipe works
Traceback (most recent call last):
  File "scratch.py", line 55, in <module>
    exit(main())
  File "scratch.py", line 51, in main
    print(test_pty())
  File "scratch.py", line 31, in test_pty
    out = pipe_output(read, write)
  File "scratch.py", line 23, in pipe_output
    return fdopen(read).read().replace('\r\n', '\n')
IOError: [Errno 5] Input/output error
```

Reproduction script:
```
#!python

from __future__ import print_function
from __future__ import unicode_literals


def pipe_output(read, write):
    from os import fork, close
    from subprocess import Popen
    if fork(): #parent
        close(write)
    else:
        close(read)
        Popen(
            ('echo', 'hi', 'there!'),
            stdout=write,
            close_fds=True,
            universal_newlines=True,
        )
        close(write)
        exit()

    from os import fdopen

    return fdopen(read).read().replace('\r\n', '\n')



def test_pty():
    from os import openpty
    read, write = openpty()

    out = pipe_output(read, write)

    assert out == 'hi there!\n', repr(out)

    return 'pty works'


def test_pipe():
    from os import pipe
    read, write = pipe()

    out = pipe_output(read, write)

    assert out == 'hi there!\n', repr(out)

    return 'pipe works'


def main():
    print(test_pipe())
    print(test_pty())


if __name__ == '__main__':
    exit(main())
```

If I create my own read-loop, I can force pypy behavior to match, but it's error prone and a huge pain. Replacing `fdopen().read()` with:

```
    from os import read as fread

    result = []
    lastread = None
    while lastread != '':
        try:
            lastread = fread(read, 1025)
        except OSError as err:
            if err.errno == 5:
                break  # slave closed
            else:
                raise
        result.append(lastread)

    close(read)
    return ''.join(result)
```




More information about the pypy-issue mailing list