You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
subprocess wait() hangs when stdin is closed #56995
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=Noneclosed_at=<Date2011-08-25.20:17:25.956>created_at=<Date2011-08-19.16:31:01.984>labels= ['type-bug', 'library']
title='subprocess wait() hangs when stdin is closed'updated_at=<Date2011-08-25.20:17:25.955>user='https://bugs.python.org/idank'
"The guys at #python-dev confirmed the same happens on 2.7 but not on 3.x."
Really? This is on gentoo, not debian, admittedly:
coelacanth ~ 11:12:36 $ python3
Python 3.1.3 (r313:86834, May 1 2011, 09:41:48)
[GCC 4.4.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> proc1 = subprocess.Popen(['cat'], stdin=subprocess.PIPE)
>>> proc2 = subprocess.Popen(['cat'], stdin=subprocess.PIPE)
>>> proc2.stdin.close()
>>> proc2.wait()
0
>>>
coelacanth ~ 11:12:13 $ python3.1
Python 3.1.3 (r313:86834, May 1 2011, 09:41:48)
[GCC 4.4.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> proc1 = subprocess.Popen(['cat'], stdin=subprocess.PIPE)
>>> proc2 = subprocess.Popen(['cat'], stdin=subprocess.PIPE)
>>> proc1.stdin.close()
>>> proc1.wait()
[hangs]
neologix commented on Aug 19, 2011
neologixmannequin
Mannequin
More actions
Hello Idan,
The following program hangs on Debian
Debian is a good choice :-)
Concerning your example, it hangs is because the file descriptor used
to communicate with proc1 is inherited when proc2 is created (FDs are
inherited upon fork by default): thus, when you call
proc1.stdin.close(), cat doesn't receive EOF on read(0), and remains
stuck.
If you close proc2's stdin and wait it first, then you don't have this problem:
because it's been created after proc1, its stdin FD has not been inherited
when you call proc2.stdin.close(), cat receives EOF from read(0), and exits
There are two reasons while it doesn't hang on Python 3.x:
it uses close_fds=True by default
it sets the pipe FDs CLOEXEC, so that they're closed when cat is executed
We can't make the change 1) in 2.7, because that's a behavior change.
We could however set the FDs used to communicate with the children CLOEXEC.
I'll work on a patch for 2.7 (but it won't be thread-safe, because
pipe2 is not exposed and there's no _posixsubprocess.c like in 3.x).
neologix commented on Aug 19, 2011
neologixmannequin
Mannequin
More actions
Here's a patch + test for 2.7.
Really? This is on gentoo, not debian, admittedly:
That's because the change of close_fds to True by default and the CLOEXEC flag were added in 3.2.
Since 3.1 is in security-fix mode only, this patch is only relevant to 2.7.
idank commented on Aug 20, 2011
idankmannequin
MannequinAuthor
More actions
Thanks for getting on top of this so quickly Charles. Setting close_fds=True worked like a charm.
You might want to add a comment in the patch that the cloexec flag is removed from the child's pipes by calling dup2() before exec() :) I was a bit baffled at first when reading the patch.
neologix commented on Aug 24, 2011
neologixmannequin
Mannequin
More actions
With comment.
I'll add a similar comment to default.
subprocess_cloexec-1.diff: I'm too tired too review the test. The subprocess.py part looks correct, except the pipe2 name. Python 3 uses "_create_pipe = _posixsubprocess.cloexec_pipe". Pick one of those.
Activity
idank commentedon Aug 19, 2011
The following program hangs on Debian, Python 2.6.6:
Changing the last two lines to:
Doesn't hang. The guys at #python-dev confirmed the same happens on 2.7 but not on 3.x.
BenWolfson commentedon Aug 19, 2011
"The guys at #python-dev confirmed the same happens on 2.7 but not on 3.x."
Really? This is on gentoo, not debian, admittedly:
[hangs]
neologix commentedon Aug 19, 2011
Hello Idan,
Debian is a good choice :-)
Concerning your example, it hangs is because the file descriptor used
to communicate with proc1 is inherited when proc2 is created (FDs are
inherited upon fork by default): thus, when you call
proc1.stdin.close(),
catdoesn't receive EOF on read(0), and remainsstuck.
If you close proc2's stdin and wait it first, then you don't have this problem:
catreceives EOF from read(0), and exitsThere are two reasons while it doesn't hang on Python 3.x:
executedTry with
"""
proc1 = subprocess.Popen(['cat'], stdin=subprocess.PIPE)
proc2 = subprocess.Popen(['cat'], stdin=subprocess.PIPE, close_fds=True)
And you'll be fine.
We can't make the change 1) in 2.7, because that's a behavior change.
We could however set the FDs used to communicate with the children CLOEXEC.
I'll work on a patch for 2.7 (but it won't be thread-safe, because
pipe2 is not exposed and there's no _posixsubprocess.c like in 3.x).
neologix commentedon Aug 19, 2011
Here's a patch + test for 2.7.
That's because the change of close_fds to True by default and the CLOEXEC flag were added in 3.2.
Since 3.1 is in security-fix mode only, this patch is only relevant to 2.7.
idank commentedon Aug 20, 2011
Thanks for getting on top of this so quickly Charles. Setting close_fds=True worked like a charm.
pitrou commentedon Aug 24, 2011
You might want to add a comment in the patch that the cloexec flag is removed from the child's pipes by calling dup2() before exec() :) I was a bit baffled at first when reading the patch.
neologix commentedon Aug 24, 2011
With comment.
I'll add a similar comment to default.
vstinner commentedon Aug 24, 2011
subprocess_cloexec-1.diff: I'm too tired too review the test. The subprocess.py part looks correct, except the pipe2 name. Python 3 uses "_create_pipe = _posixsubprocess.cloexec_pipe". Pick one of those.
rosslagerwall commentedon Aug 25, 2011
Patch looks good after Victor's comment.
python-dev commentedon Aug 25, 2011
New changeset 498b03a55297 by Charles-François Natali in branch '2.7':
Issue bpo-12786: Set communication pipes used by subprocess.Popen CLOEXEC to avoid
http://hg.python.org/cpython/rev/498b03a55297
neologix commentedon Aug 25, 2011
Patch committed.
Idan, thanks for the report.