[Python-checkins] cpython (merge 3.4 -> default): Merge 3.4 (asyncio)

victor.stinner python-checkins at python.org
Thu Dec 11 23:31:45 CET 2014


https://hg.python.org/cpython/rev/2e636ac3fdbb
changeset:   93837:2e636ac3fdbb
parent:      93835:7c2811521261
parent:      93836:17f5ddf15ced
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Thu Dec 11 23:30:31 2014 +0100
summary:
  Merge 3.4 (asyncio)

files:
  Lib/asyncio/unix_events.py               |  22 ++++++++++++
  Lib/test/test_asyncio/test_subprocess.py |  21 +++++++++++
  2 files changed, 43 insertions(+), 0 deletions(-)


diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py
--- a/Lib/asyncio/unix_events.py
+++ b/Lib/asyncio/unix_events.py
@@ -547,6 +547,22 @@
             self._loop = None
 
 
+if hasattr(os, 'set_inheritable'):
+    # Python 3.4 and newer
+    _set_inheritable = os.set_inheritable
+else:
+    import fcntl
+
+    def _set_inheritable(fd, inheritable):
+        cloexec_flag = getattr(fcntl, 'FD_CLOEXEC', 1)
+
+        old = fcntl.fcntl(fd, fcntl.F_GETFD)
+        if not inheritable:
+            fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag)
+        else:
+            fcntl.fcntl(fd, fcntl.F_SETFD, old & ~cloexec_flag)
+
+
 class _UnixSubprocessTransport(base_subprocess.BaseSubprocessTransport):
 
     def _start(self, args, shell, stdin, stdout, stderr, bufsize, **kwargs):
@@ -558,6 +574,12 @@
             # other end).  Notably this is needed on AIX, and works
             # just fine on other platforms.
             stdin, stdin_w = self._loop._socketpair()
+
+            # Mark the write end of the stdin pipe as non-inheritable,
+            # needed by close_fds=False on Python 3.3 and older
+            # (Python 3.4 implements the PEP 446, socketpair returns
+            # non-inheritable sockets)
+            _set_inheritable(stdin_w.fileno(), False)
         self._proc = subprocess.Popen(
             args, shell=shell, stdin=stdin, stdout=stdout, stderr=stderr,
             universal_newlines=False, bufsize=bufsize, **kwargs)
diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py
--- a/Lib/test/test_asyncio/test_subprocess.py
+++ b/Lib/test/test_asyncio/test_subprocess.py
@@ -198,6 +198,27 @@
         self.assertTrue(transport.pause_reading.called)
         self.assertTrue(transport.resume_reading.called)
 
+    def test_stdin_not_inheritable(self):
+        # Tulip issue #209: stdin must not be inheritable, otherwise
+        # the Process.communicate() hangs
+        @asyncio.coroutine
+        def len_message(message):
+            code = 'import sys; data = sys.stdin.read(); print(len(data))'
+            proc = yield from asyncio.create_subprocess_exec(
+                                          sys.executable, '-c', code,
+                                          stdin=asyncio.subprocess.PIPE,
+                                          stdout=asyncio.subprocess.PIPE,
+                                          stderr=asyncio.subprocess.PIPE,
+                                          close_fds=False,
+                                          loop=self.loop)
+            stdout, stderr = yield from proc.communicate(message)
+            exitcode = yield from proc.wait()
+            return (stdout, exitcode)
+
+        output, exitcode = self.loop.run_until_complete(len_message(b'abc'))
+        self.assertEqual(output.rstrip(), b'3')
+        self.assertEqual(exitcode, 0)
+
 
 if sys.platform != 'win32':
     # Unix

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list