Skip to content
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

Popen.communicate not ignoring BrokenPipeError #70560

Closed
memeplex mannequin opened this issue Feb 17, 2016 · 17 comments
Closed

Popen.communicate not ignoring BrokenPipeError #70560

memeplex mannequin opened this issue Feb 17, 2016 · 17 comments
Assignees
Labels
stdlib Python modules in the Lib dir topic-asyncio type-bug An unexpected behavior, bug, or error

Comments

@memeplex
Copy link
Mannequin

memeplex mannequin commented Feb 17, 2016

BPO 26372
Nosy @gvanrossum, @gpshead, @vstinner, @ambv, @vadmium, @serhiy-storchaka, @1st1
Files
  • broken_pipe_error.patch
  • 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:

    assignee = 'https://github.com/gpshead'
    closed_at = <Date 2016-06-05.04:30:52.838>
    created_at = <Date 2016-02-17.01:28:32.540>
    labels = ['type-bug', 'library', 'expert-asyncio']
    title = 'Popen.communicate not ignoring BrokenPipeError'
    updated_at = <Date 2016-06-05.04:30:52.837>
    user = 'https://bugs.python.org/memeplex'

    bugs.python.org fields:

    activity = <Date 2016-06-05.04:30:52.837>
    actor = 'gregory.p.smith'
    assignee = 'gregory.p.smith'
    closed = True
    closed_date = <Date 2016-06-05.04:30:52.838>
    closer = 'gregory.p.smith'
    components = ['Library (Lib)', 'asyncio']
    creation = <Date 2016-02-17.01:28:32.540>
    creator = 'memeplex'
    dependencies = []
    files = ['41941']
    hgrepos = []
    issue_num = 26372
    keywords = ['patch']
    message_count = 17.0
    messages = ['260373', '260387', '260390', '260391', '260392', '260405', '260414', '260415', '260418', '260763', '266499', '267204', '267206', '267212', '267245', '267292', '267367']
    nosy_count = 9.0
    nosy_names = ['gvanrossum', 'gregory.p.smith', 'vstinner', 'memeplex', 'lukasz.langa', 'python-dev', 'martin.panter', 'serhiy.storchaka', 'yselivanov']
    pr_nums = []
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue26372'
    versions = ['Python 2.7', 'Python 3.5', 'Python 3.6']

    @memeplex
    Copy link
    Mannequin Author

    memeplex mannequin commented Feb 17, 2016

    When not using a timeout, communicate will raise a BrokenPipeError if the command returns an error code. For example:

    sp = subprocess.Popen('cat --not-an-option', shell=True, stdin=subprocess.PIPE)
    time.sleep(.2)
    sp.communicate(b'hi\n')

    This isn't consistent with the behavior of communicate with a timeout, which doesn't raise the exception. Moreover, there is even a comment near the point of the exception stating that communicate must ignore BrokenPipeError:

        def _stdin_write(self, input):
            if input:
                try:
                    self.stdin.write(input)
                except BrokenPipeError:
                    # communicate() must ignore broken pipe error
                    pass
                ....
            self.stdin.close()

    Obviously, the problem is that self.stdin.close() is outside the except clause.

    @memeplex memeplex mannequin added stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error labels Feb 17, 2016
    @vadmium
    Copy link
    Member

    vadmium commented Feb 17, 2016

    Seems a reasonable proposal to me. Originally the bufsize parameter defaulted to 0 so this wouldn’t have been such a problem. Explicitly setting bufsize=0 should be a decent workaround.

    @vstinner
    Copy link
    Member

    This isn't consistent with the behavior of communicate with a timeout

    Right, it looks like BrokenPipeError on writing into stdin is ignored in some cases, but not in all cases.

    Attached patch for Python 3.6 adds two try/except BrokenPipeError with two unit tests.

    It looks like Python 2.7 has a similar bug: stdin.close() is not surrounded by try/except BrokenPipeError.

    @vstinner
    Copy link
    Member

    Explicitly setting bufsize=0 should be a decent workaround.

    It kills performances, no?

    @vstinner
    Copy link
    Member

    It looks like asyncio.subprocess has a similar issue in Process._feed_stdin, but I'm not sure that stdin.close() can trigger BrokenPipeError. Well, it wouldn't hurd to protect stdin.close() with a try/except BrokenPipeError too ;-)

    @vstinner
    Copy link
    Member

    See also issue bpo-23570: Change "with subprocess.Popen():" (context manager) to ignore broken pipe error.

    @vadmium
    Copy link
    Member

    vadmium commented Feb 18, 2016

    Looking over the code for communicate(), I think setting bufsize=0 should not cause a performance problem in the original use case. Communicate() either calls stdin.write() once, or bypasses the file object and calls os.write(). Only if stdin, stdout, etc were used before communicate(), then there could be a problem (and subtly different behaviour).

    I left some suggestions on the code review.

    @vstinner
    Copy link
    Member

    bufsize impacts all streams, no only stdin, no?

    @vadmium
    Copy link
    Member

    vadmium commented Feb 18, 2016

    Yes I understand bufsize (and universal_newlines) affects any of stdin, stdout and stderr that is set to PIPE.

    @serhiy-storchaka
    Copy link
    Member

    This is just the bug I reported in msg236951.

    Text streams are buffered, thus setting bufsize=0 does not help if universal_newlines=True.

    Added comments on Rietveld.

    @serhiy-storchaka
    Copy link
    Member

    Ping.

    @gpshead gpshead self-assigned this May 28, 2016
    @gpshead
    Copy link
    Member

    gpshead commented Jun 4, 2016

    Lukas - cc'ing you just in case this bug is related to the asyncio subprocess race condition-ish problems you were talking about at pycon.

    @gpshead
    Copy link
    Member

    gpshead commented Jun 4, 2016

    the bot hasn't piped up with the changesets. these are the 3.5 and default fixes:

    remote: notified python-checkins@python.org of incoming changeset 883cfb3e28f9
    remote: notified python-checkins@python.org of incoming changeset 78e81de6d447

    @ambv
    Copy link
    Contributor

    ambv commented Jun 4, 2016

    Thanks, I looked at this issue just today :)

    @vadmium
    Copy link
    Member

    vadmium commented Jun 4, 2016

    Maybe use os.devnull instead of "/dev/null"?

    http://buildbot.python.org/all/builders/AMD64%20Windows7%20SP1%203.x/builds/7728/steps/test/logs/stdio
    ======================================================================
    ERROR: test_communicate_BrokenPipeError_stdin_flush (test.test_subprocess.ProcessTestCase)
    ----------------------------------------------------------------------

    Traceback (most recent call last):
      File "C:\buildbot.python.org\3.x.kloth-win64\build\lib\test\test_subprocess.py", line 1267, in test_communicate_BrokenPipeError_stdin_flush
        open('/dev/null', 'wb') as dev_null:
    FileNotFoundError: [Errno 2] No such file or directory: '/dev/null'

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Jun 4, 2016

    New changeset 3a560525ca50 by Gregory P. Smith in branch '3.5':
    bpo-26372 - use os.devnull instead of /dev/null
    https://hg.python.org/cpython/rev/3a560525ca50

    New changeset 52e331b86f2b by Gregory P. Smith in branch 'default':
    bpo-26372 - use os.devnull instead of /dev/null
    https://hg.python.org/cpython/rev/52e331b86f2b

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Jun 5, 2016

    New changeset e89eb7935ca9 by Gregory P. Smith in branch 'default':
    merge from 3.5. (moves the bpo-26372 tests to the proper class)
    https://hg.python.org/cpython/rev/e89eb7935ca9

    @gpshead gpshead closed this as completed Jun 5, 2016
    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    stdlib Python modules in the Lib dir topic-asyncio type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    5 participants