Issue1736483
Created on 2007-06-13 13:41 by cpegeric, last changed 2010-02-24 17:42 by gregory.p.smith. This issue is now closed.
| Messages (11) | |||
|---|---|---|---|
| msg32314 - (view) | Author: Eric (cpegeric) | Date: 2007-06-13 13:41 | |
after calling os.popen('yes | echo hello'), the process never returns.
|
|||
| msg32315 - (view) | Author: Ilguiz Latypov (ilgiz) | Date: 2007-06-13 17:07 | |
Could you try the same command from your shell?
I am guessing "yes" will write an error message about the broken pipe to stderr.
$ python -c 'import sys, os; sys.stdout.write(os.popen("yes | echo hello").read())'
yes: standard output: Broken pipe
yes: write error
hello
$ python -c 'import sys, os; sys.stdout.write(os.popen3("yes | echo hello")[1].read())'
hello
|
|||
| msg32316 - (view) | Author: Eric (cpegeric) | Date: 2007-06-14 01:28 | |
command line also get stuck. The OS is MacOSX. Python version 2.3.5. Will it help update to new version?
I quited the program by Ctrl-C.
python -c 'import sys, os; sys.stdout.write(os.popen("yes | echo hello").read())'
^CTraceback (most recent call last):
File "<string>", line 1, in ?
KeyboardInterrupt
% python -c 'import sys, os; sys.stdout.write(os.popen3("yes | echo hello")[1].read())'
^CTraceback (most recent call last):
File "<string>", line 1, in ?
KeyboardInterrupt
|
|||
| msg32317 - (view) | Author: Ilguiz Latypov (ilgiz) | Date: 2007-06-14 02:24 | |
I've realized my suggestion was not precise. I meant asking to run the argument to popen() rather than popen(). That is, I would run this from command line to see if there is an issue with the shell: $ yes | echo hello |
|||
| msg32318 - (view) | Author: Eric (cpegeric) | Date: 2007-06-14 02:46 | |
sorry for the misunderstanding. Here is the result. % yes | echo hello hello % echo $? 0 % |
|||
| msg32319 - (view) | Author: Ilguiz Latypov (ilgiz) | Date: 2007-06-14 03:15 | |
It appears your "yes" does not catch SIGPIPE. I've reproduced the issue with
$ python -c 'import sys, os; sys.stdout.write(os.popen("while :; do echo yes ; done | echo hello").read())'
Traceback (most recent call last):
File "<string>", line 1, in <module>
KeyboardInterrupt
The documentation on Python module signal says SIGPIPE is ignored by Python as well. My work-around to this was to catch SIGPIPE, but the GNU C library would terminate the whole script.
$ python -c 'import sys, os, signal; signal.signal(signal.SIGPIPE, signal.SIG_DFL); sys.stdout.write(os.popen("while :; do echo yes ; done | echo hello").read())'
hello
http://www.gnu.org/software/libc/manual/html_node/Operation-Error-Signals.html
Perhaps, writing own signal handler might help.
|
|||
| msg32320 - (view) | Author: Ilguiz Latypov (ilgiz) | Date: 2007-06-14 03:22 | |
The SIG_DFL default handler seems to terminate the current process (argument to popen()), not Python script. |
|||
| msg32321 - (view) | Author: Eric (cpegeric) | Date: 2007-06-14 03:49 | |
It works now. thank you. |
|||
| msg99642 - (view) | Author: Ilya Sandler (isandler) | Date: 2010-02-21 04:40 | |
I don't think this is a bug in python (see below for analysis). Furthermore, os.popen() is deprecated, so I think this issue can be closed.
Here is my understanding of what's happening.
When you execute :
python -c 'import sys, os; sys.stdout.write(os.popen("while :; do echo yes ; done | echo hello").read())'
popen() forks and then execs() a /bin/sh like this
/bin/sh -c "while :; do echo yes ; done | echo hello"
But exec() (on Linux at least) inherits the signal handling from the pre-exec process for the signals which were set to SIG_IGN or SIG_DFL (see e.g here: http://www.gnu.org/software/libc/manual/html_node/Initial-Signal-Actions.html), so in this case shell will inherit SIG_IGN setting from python for SIGPIPE.
Furthermore, the "sh" manpage explicitly says that shell will wait for all processes in the pipeline.
So, the sequence of events will be as follows: echo exits, SIGPIPE is delivered to the shell and is ignored by the shell and so the shell keeps running the while loop forever, so .read() call never reaches the eof and your script blocks.
The original "yes|echo" example on MacOsX has likely been caused by the same sequence of events. (if "yes" inherits signal handling from shell, then "yes|echo"
would not block when invoked from command line, but would block when invoked from python)
Installling your own SIGPIPE handler (or resetting SIGPIPE to SIG_DFL as ilgiz suggested) should work around this issue.
|
|||
| msg99646 - (view) | Author: R. David Murray (r.david.murray) * ![]() |
Date: 2010-02-21 05:29 | |
See also issue 1652, noting as well that os.popen is implemented via subprocess in py3k. |
|||
| msg100054 - (view) | Author: Gregory P. Smith (gregory.p.smith) * ![]() |
Date: 2010-02-24 17:42 | |
issue 1652 will take care of this problem. i'm working on it. |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2010-02-24 17:42:46 | gregory.p.smith | set | status: open -> closed nosy: + gregory.p.smith messages: + msg100054 superseder: subprocess should have an option to restore SIGPIPE to default action resolution: wont fix |
| 2010-02-21 05:29:56 | r.david.murray | set | priority: normal nosy: + r.david.murray messages: + msg99646 |
| 2010-02-21 04:40:20 | isandler | set | nosy:
+ isandler messages: + msg99642 |
| 2009-03-31 01:19:34 | ajaksu2 | set | priority: normal -> (no value) stage: test needed type: behavior versions: + Python 2.6, - Python 2.3 |
| 2007-06-13 13:41:20 | cpegeric | create | |
