New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test_communicate_epipe() of test_subprocess fails randomly on AMD64 Windows7 SP1 3.x #74603
Comments
Hum, the following failing looks like bpo-19612, but it seems like the code took the "raise" path instead of the "pass" fails.
On AMD64 Windows7 SP1 3.x: ... Traceback (most recent call last):
File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\test_subprocess.py", line 1219, in test_communicate_epipe
p.communicate(b"x" * 2**20)
File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\subprocess.py", line 838, in communicate
stdout, stderr = self._communicate(input, endtime, timeout)
File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\subprocess.py", line 1072, in _communicate
self._stdin_write(input)
File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\subprocess.py", line 778, in _stdin_write
self.stdin.write(input)
OSError: [Errno 22] Invalid argument Ran 261 tests in 43.540s FAILED (errors=1, skipped=150) |
Seeing EINVAL here while the child process is alive could mean the read end of the pipe was closed. For example: >>> import time, subprocess
>>> cmd = 'python -c "import os, time; os.close(0); time.sleep(15)"'
>>> p = subprocess.Popen(cmd, stdin=subprocess.PIPE, bufsize=0)
>>> time.sleep(5); p.communicate(b'spam')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Program Files\Python36\lib\subprocess.py", line 821, in communicate
self._stdin_write(input)
File "C:\Program Files\Python36\lib\subprocess.py", line 776, in _stdin_write
self.stdin.write(input)
OSError: [Errno 22] Invalid argument If buffered, the error would instead occur at self.stdin.close(). Both cases are currently checked, but the error is only ignored when the child process is still alive. The underlying Windows error is ERROR_NO_DATA. If we could know that for certain, then we could ignore it as a BrokenPipeError. Currently all we have to go on from _Py_write is the CRT's EINVAL errno value. In contrast, when creating an OSError from the Windows last error value, winerror_to_errno() maps ERROR_NO_DATA as EPIPE. |
This should instead be the error is only ignored when child process is *no longer* alive. |
Would you like to work on a PR Eryk? It seems like you understand the bug |
Addressing the underlying problem would require rewriting _Py_read and _Py_write_impl to directly call ReadFile and WriteFile instead of the CRT read and write functions. Barring that, on Windows _stdin_write would have to always ignore EINVAL. |
Basically, Windows EINVAL here looks like UNIX EPIPE. I agree to always I added the poll() check when I added the EINVAL test because I don't know Your example makes it perfectly clear. In short, Python must behave the same on Windows and UNIX on your example: |
So, would you mind to write such PR? |
The bug should now be fixed. EINVAL is now also ignored even if the process is still running, same behaviour than UNIX with EPIPE. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: