Commit 434e7903 authored by torne@chromium.org's avatar torne@chromium.org

Work around race condition in subprocess.

There's a race condition in python's subprocess module, and gclient uses
it heavily while multithreaded. Avoid the race by locking around calls
to subprocess.Popen's constructor. Detailed explanation in the bug.

BUG=531561

Review URL: https://codereview.chromium.org/1343783004

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@296685 0039d316-1c4b-4281-b951-d872f2087c98
parent 45453140
......@@ -181,6 +181,14 @@ class Popen(subprocess.Popen):
Note: Popen() can throw OSError when cwd or args[0] doesn't exist. Translate
exceptions generated by cygwin when it fails trying to emulate fork().
"""
# subprocess.Popen.__init__() is not threadsafe; there is a race between
# creating the exec-error pipe for the child and setting it to CLOEXEC during
# which another thread can fork and cause the pipe to be inherited by its
# descendents, which will cause the current Popen to hang until all those
# descendents exit. Protect this with a lock so that only one fork/exec can
# happen at a time.
popen_lock = threading.Lock()
def __init__(self, args, **kwargs):
# Make sure we hack subprocess if necessary.
hack_subprocess()
......@@ -234,7 +242,8 @@ class Popen(subprocess.Popen):
self.returncode = None
try:
super(Popen, self).__init__(args, **kwargs)
with self.popen_lock:
super(Popen, self).__init__(args, **kwargs)
except OSError, e:
if e.errno == errno.EAGAIN and sys.platform == 'cygwin':
# Convert fork() emulation failure into a CygwinRebaseError().
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment