-
-
Notifications
You must be signed in to change notification settings - Fork 29.9k
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
subprocess is not EINTR-safe #41185
Comments
The subprocess module is not safe for use with signals, The problem was first noticed by John P Speno. |
Logged In: YES One way of testing subprocess for signal-safeness is to import signal
signal.signal(signal.SIGALRM, lambda x,y: 1)
signal.alarm(1)
import time
time.sleep(0.99) Then run test_subprocess.py. |
Logged In: YES I've hit this on a Solaris 9 box without explicitly using SunOS 5.9 Generic_112233-01 sun4u sparc SUNW,Sun-Fire-280R |
I just got two different Ubuntu bug reports about this problem as well, and I'm unsure how to circumvent this at the application level. http://librarian.launchpad.net/6514580/Traceback.txt (from https://launchpad.net/bugs/87292 and its duplicate) |
I updated Peter's original patch to 2.5+svn fixes and added proper tests to test_subprocess.py. It works great now. What do you think about this approach? Fixing it only in submodule feels a bit strange, but then again, this is meant to be an easy to use abstraction, and most of the people that were hit by this (according to Google) encountered the problem in subprocess. I don't see how to attach something here, so I attached the updated patch to the Ubuntu bug (https://launchpad.net/bugs/87292): http://librarian.launchpad.net/6807594/subprocess-eintr-safety.patch Thanks, Martin |
Updated patch: http://librarian.launchpad.net/6820347/subprocess-eintr-safety.patch I removed the _read_all() function, since that broke the 1 MB exception limit and does not seem to be necessary in the first place. |
I hit this in Python 2.5.1 on an Intel Mac in a PyQt application. mpitt's patch at http://librarian.launchpad.net/6820347/subprocess-eintr-safety.patch fixed it for me. |
In normal application code that signal.alarm is called for a reason. And What was the signal interrupting the read calls? maybe SIGPIPE? |
Of course the signal handler may raise an exception, so my last argument |
I think the proper behavior on EINTR may depend on which subprocess call Regarding the patch, a wrapper function called as |
fyi - To fix issue bpo-2113 I added handling of a select.error errno.EINTR |
I think this should be resolved in 2.6/3.0 if possible. Especially if |
I'd like to suggest to rise the priority of this bug. |
Two remarks: 2 - the patch seems to replace all calls to os.write, os.read and |
its too late in the release process for subprocess internals being EINTR |
Upgrade subprocess.py patch to 25-maint r65475 |
Factorized try-except code, merged r65475 from 25-maint. |
Ups, forgot a _no_intr around select.select Index: subprocess.py --- subprocess.py (revisione 19645)
+++ subprocess.py (copia locale)
@@ -1178,7 +1178,7 @@
input_offset = 0
while read_set or write_set:
- rlist, wlist, xlist = select.select(read_set,
write_set, [])
+ rlist, wlist, xlist = _no_intr(select.select)(read_set,
write_set, [])
if self.stdin in wlist:
# When select has indicated that the file is
writable, |
Python 2.5.3 is near but the I think the fix in |
naufraghi> there are a lot of other places where EINTR Can you write a list of these places? |
Please have a look at the proposed patch: http://bugs.python.org/file11511/subprocess-eintr-safety-25maint- the list is more or less the patch itself. |
Instead of define a method for each "syscall", you can write a generic def no_intr(self, func, *args, **kw):
while True:
try:
return func(*args, **kw)
except OSError, e:
if e.errno == errno.EINTR:
continue
else:
raise
x=_waitpid_no_intr(pid, options) becomes x=no_intr(os.waitpid, pid,
options). |
Oh, the new patch (subprocess-retry-on-EINTR-std-in-out-err.diff) has |
no EINTR patch upgraded to 25-maint r65475 that protects: *) all direct calls I hope :P |
Since Python 2.5 only accept security fixes, you should update your |
File Now what? The process started, but I have no way of knowing when it try/except in my code can never help. It must be put in the stdlib. Or, if this is too egregious, then the docs should scream that File This os.read is a byproduct of something the Popen.__init__ The process is started, then this is aborted before the Popen.stdout and |
Another instance of a blocking function within subprocess not being protected against EINTR Python 2.6.4, subprocess.py, Popen function, line 1115: If a signal arrives while blocked in this read, the EINTR/OSError is passed up to whatever called subprocess.Popen. Retrying the Popen doesn't help because the child process may already have started but the caller has no way to know this nor does the caller have any control over the child process. === In the example code, the first subprocess.Popen starts without issue but while in the second Popen call, p1's SIGCHLD is received by the parent. The "preexec_fn = lambda : time.sleep(2)" in the second Popen is a little contrived but serves to guarantee that the SIGCHLD will break the Popen for the purposes of the demonstration. I have seen this failure mode when using vanilla Popen calls although you have to be lucky/unlucky to see it. ==== This is in python 2.6.4:
==== I expect the fix is equivalent to cmiller's trunk-diff-unified.txt |
fixed in trunk r78523. backporting to 2.6 and 3.1. |
merged into 2.6 and 3.1 release branches. |
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:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: