This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author akira
Recipients akira, hanno, terry.reedy
Date 2014-05-03.06:50:23
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <>
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)

"(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

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

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
      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:
os.popen() in Python 3:
Date User Action Args
2014-05-03 06:50:25akirasetrecipients: + akira, terry.reedy, hanno
2014-05-03 06:50:25akirasetmessageid: <>
2014-05-03 06:50:25akiralinkissue20866 messages
2014-05-03 06:50:23akiracreate