Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d625a18

Browse files
committed
Merge 3.4 (asyncio)
2 parents eb1a995 + 1e40f10 commit d625a18

2 files changed

Lines changed: 43 additions & 0 deletions

File tree

Lib/asyncio/unix_events.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,22 @@ def _call_connection_lost(self, exc):
547547
self._loop = None
548548

549549

550+
if hasattr(os, 'set_inheritable'):
551+
# Python 3.4 and newer
552+
_set_inheritable = os.set_inheritable
553+
else:
554+
import fcntl
555+
556+
def _set_inheritable(fd, inheritable):
557+
cloexec_flag = getattr(fcntl, 'FD_CLOEXEC', 1)
558+
559+
old = fcntl.fcntl(fd, fcntl.F_GETFD)
560+
if not inheritable:
561+
fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag)
562+
else:
563+
fcntl.fcntl(fd, fcntl.F_SETFD, old & ~cloexec_flag)
564+
565+
550566
class _UnixSubprocessTransport(base_subprocess.BaseSubprocessTransport):
551567

552568
def _start(self, args, shell, stdin, stdout, stderr, bufsize, **kwargs):
@@ -558,6 +574,12 @@ def _start(self, args, shell, stdin, stdout, stderr, bufsize, **kwargs):
558574
# other end). Notably this is needed on AIX, and works
559575
# just fine on other platforms.
560576
stdin, stdin_w = self._loop._socketpair()
577+
578+
# Mark the write end of the stdin pipe as non-inheritable,
579+
# needed by close_fds=False on Python 3.3 and older
580+
# (Python 3.4 implements the PEP 446, socketpair returns
581+
# non-inheritable sockets)
582+
_set_inheritable(stdin_w.fileno(), False)
561583
self._proc = subprocess.Popen(
562584
args, shell=shell, stdin=stdin, stdout=stdout, stderr=stderr,
563585
universal_newlines=False, bufsize=bufsize, **kwargs)

Lib/test/test_asyncio/test_subprocess.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,27 @@ def test_pause_reading():
198198
self.assertTrue(transport.pause_reading.called)
199199
self.assertTrue(transport.resume_reading.called)
200200

201+
def test_stdin_not_inheritable(self):
202+
# Tulip issue #209: stdin must not be inheritable, otherwise
203+
# the Process.communicate() hangs
204+
@asyncio.coroutine
205+
def len_message(message):
206+
code = 'import sys; data = sys.stdin.read(); print(len(data))'
207+
proc = yield from asyncio.create_subprocess_exec(
208+
sys.executable, '-c', code,
209+
stdin=asyncio.subprocess.PIPE,
210+
stdout=asyncio.subprocess.PIPE,
211+
stderr=asyncio.subprocess.PIPE,
212+
close_fds=False,
213+
loop=self.loop)
214+
stdout, stderr = yield from proc.communicate(message)
215+
exitcode = yield from proc.wait()
216+
return (stdout, exitcode)
217+
218+
output, exitcode = self.loop.run_until_complete(len_message(b'abc'))
219+
self.assertEqual(output.rstrip(), b'3')
220+
self.assertEqual(exitcode, 0)
221+
201222

202223
if sys.platform != 'win32':
203224
# Unix

0 commit comments

Comments
 (0)