akira added the comment: I can't reproduce it on Ubuntu 12.04 with Python 2.7.3, 2.7.6, 3.2, tip -- no segfault.
It prints the expected output on both Python 2 and 3: (standard input) io-error "(standard input)" is printed by grep due to --files-with-match option io-error (Broken pipe) is because grep exits as soon as it sees the first decimal zero due to `--files-with-match 0` args without waiting for all input to arrive therefore the subsequent attempts by the parent python process to write to grep fail with BrokenPipeError. You could get the same behaviour using "python -c pass" instead of grep. If the input is less than an OS pipe buffer (~64K) then fd.write succeeds because the system call os.write(pipe, input) succeeds whether the child process reads its input or not. Introducing a delay before writing to the child process generates the error reliably even for small input because the delay allows the child process to exit. Despite being stdio-based Python 2 io behaves the same in this case. SIGPIPE is suppressed in python by default therefore the error is generated instead of dying on SIGPIPE. If the signal is restored: import signal signal.signal(signal.SIGPIPE, signal.SIG_DFL) # restore SIGPIPE then the parent process dies on SIGPIPE (if input is larger than the OS pipe buffer of if the child process is already exited -- the same as for BrokenPipeError). The behaviour is the same ("Broken pipe" for large input) if syscalls are used directly instead of os.popen: #!/usr/bin/env python from sys import argv, exit from os import close, dup2, execlp, fork, pipe, wait, write n = int(argv[1]) if len(argv) > 1 else 100000000 n = (n // 2) * 2 # make it even assert n > 1 in_, out = pipe() if fork() == 0: # child close(out) # close unused write end of the pipe dup2(in_, 0) # redirect stdin to the pipe close(in_) execlp('/bin/grep', '/bin/grep', '--files-with-match', '0') else: # parent close(in_) # close unused read end of the pipe while n > 1: n -= write(out, b'0\n' * (n // 2)) # write input to the child close(out) # no more input exit(wait()[1]) # wait for the child to exit assert 0 If you meant something else; you could write more specific test. For reference: os.popen() in Python 2: http://hg.python.org/cpython/file/2.7/Modules/posixmodule.c#l4560 os.popen() in Python 3: http://hg.python.org/cpython/file/3.4/Lib/os.py#l928 ---------- nosy: +akira _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue20866> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com