Handle closed sys.__stdin__, for multiprocessing
authorZac Medico <zmedico@gentoo.org>
Sat, 15 Dec 2012 22:04:28 +0000 (14:04 -0800)
committerZac Medico <zmedico@gentoo.org>
Sat, 15 Dec 2012 22:04:28 +0000 (14:04 -0800)
Buggy code in python's multiprocessing/process.py closes sys.stdin and
reassigns it to open(os.devnull), but fails to update the corresponding
__stdin__ reference. So, detect that case and handle it appropriately.
The buggy code is visible in http://hg.python.org/lookup/r73708.

bin/dispatch-conf
pym/_emerge/BinpkgFetcher.py
pym/_emerge/SpawnProcess.py
pym/portage/__init__.py
pym/portage/getbinpkg.py
pym/portage/package/ebuild/doebuild.py
pym/portage/package/ebuild/fetch.py
pym/portage/process.py

index e5f768056bb8b24161725627dc82bd430b045aab..479647edee07ce6b51d18a19e3583d4a2789b0d9 100755 (executable)
@@ -462,7 +462,7 @@ def spawn_shell(cmd):
         sys.__stdout__.flush()
         sys.__stderr__.flush()
         spawn([shell, "-c", cmd], env=os.environ,
-            fd_pipes = {  0 : sys.__stdin__.fileno(),
+            fd_pipes = {  0 : portage._get_stdin().fileno(),
                           1 : sys.__stdout__.fileno(),
                           2 : sys.__stderr__.fileno()})
     else:
index 1913b44311ba145b11508f84037f1ba168ace4be..14f2552cb161308944a88534b348aea6558a80ee 100644 (file)
@@ -91,7 +91,7 @@ class BinpkgFetcher(SpawnProcess):
                # Redirect all output to stdout since some fetchers like
                # wget pollute stderr (if portage detects a problem then it
                # can send it's own message to stderr).
-               fd_pipes.setdefault(0, sys.__stdin__.fileno())
+               fd_pipes.setdefault(0, portage._get_stdin().fileno())
                fd_pipes.setdefault(1, sys.__stdout__.fileno())
                fd_pipes.setdefault(2, sys.__stdout__.fileno())
 
index d18512b348d54be6e08e5fef5742d24b87e12482..45d7095178ec964ca3a515cb0caf6e6a99aae51d 100644 (file)
@@ -50,7 +50,7 @@ class SpawnProcess(SubProcess):
                        null_input = os.open('/dev/null', os.O_RDWR)
                        fd_pipes[0] = null_input
 
-               fd_pipes.setdefault(0, sys.__stdin__.fileno())
+               fd_pipes.setdefault(0, portage._get_stdin().fileno())
                fd_pipes.setdefault(1, sys.__stdout__.fileno())
                fd_pipes.setdefault(2, sys.__stderr__.fileno())
 
index 3e634b53b9fa644b56bbca4e9c0dccf66bb1c77b..96a4fa98c3d31d97c3f9e229ef299c29377db150 100644 (file)
@@ -339,6 +339,17 @@ _internal_warnings = False
 
 _sync_disabled_warnings = False
 
+def _get_stdin():
+       """
+       Buggy code in python's multiprocessing/process.py closes sys.stdin
+       and reassigns it to open(os.devnull), but fails to update the
+       corresponding __stdin__ reference. So, detect that case and handle
+       it appropriately.
+       """
+       if not sys.__stdin__.closed:
+               return sys.__stdin__
+       return sys.stdin
+
 def _shell_quote(s):
        """
        Quote a string in double-quotes and use backslashes to
index 28b18a00f5b89b84de967e2b23db86aabf06ded5..947bd3e92a1d8ab82846728eb4f7343f3251f56b 100644 (file)
@@ -499,7 +499,7 @@ def file_get(baseurl,dest,conn=None,fcmd=None,filename=None):
        myfetch = portage.util.shlex_split(fcmd)
        myfetch = [varexpand(x, mydict=variables) for x in myfetch]
        fd_pipes= {
-               0:sys.__stdin__.fileno(),
+               0:portage._get_stdin().fileno(),
                1:sys.__stdout__.fileno(),
                2:sys.__stdout__.fileno()
        }
index a735ea81b3038fc1be722c946c17bb5eeb75a3e1..855c62aede748b147cab69fe041eb8aefcbd4666 100644 (file)
@@ -718,7 +718,7 @@ def doebuild(myebuild, mydo, _unused=None, settings=None, debug=0, listonly=0,
                                mysettings["dbkey"] = ""
                                pr, pw = os.pipe()
                                fd_pipes = {
-                                       0:sys.__stdin__.fileno(),
+                                       0:portage._get_stdin().fileno(),
                                        1:sys.__stdout__.fileno(),
                                        2:sys.__stderr__.fileno(),
                                        9:pw}
@@ -1402,7 +1402,7 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, fakero
        fd_pipes = keywords.get("fd_pipes")
        if fd_pipes is None:
                fd_pipes = {
-                       0:sys.__stdin__.fileno(),
+                       0:portage._get_stdin().fileno(),
                        1:sys.__stdout__.fileno(),
                        2:sys.__stderr__.fileno(),
                }
index 59d45be0589a9767dbf1ae1b5ac36223a3036c44..0a7bf10bba27590a245116bc0e55e7a84feb6eb8 100644 (file)
@@ -64,7 +64,7 @@ def _spawn_fetch(settings, args, **kwargs):
        if "fd_pipes" not in kwargs:
 
                kwargs["fd_pipes"] = {
-                       0 : sys.__stdin__.fileno(),
+                       0 : portage._get_stdin().fileno(),
                        1 : sys.__stdout__.fileno(),
                        2 : sys.__stdout__.fileno(),
                }
index fbfbde04916cd64882407a317f3160c618a59bba..63c315423262c36fd3477c6f519a56440ad01bfe 100644 (file)
@@ -226,7 +226,7 @@ def spawn(mycommand, env={}, opt_name=None, fd_pipes=None, returnpid=False,
        # default to propagating our stdin, stdout and stderr.
        if fd_pipes is None:
                fd_pipes = {
-                       0:sys.__stdin__.fileno(),
+                       0:portage._get_stdin().fileno(),
                        1:sys.__stdout__.fileno(),
                        2:sys.__stderr__.fileno(),
                }