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

Skip to content

Commit 02ba73c

Browse files
committed
Merge with 3.1
2 parents 4333aff + 4f61b02 commit 02ba73c

4 files changed

Lines changed: 56 additions & 12 deletions

File tree

Lib/subprocess.py

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ class Popen(args, bufsize=0, executable=None,
345345
import signal
346346
import builtins
347347
import warnings
348+
import errno
348349

349350
# Exception classes used by this module.
350351
class CalledProcessError(Exception):
@@ -376,7 +377,6 @@ class pywintypes:
376377
else:
377378
import select
378379
_has_poll = hasattr(select, 'poll')
379-
import errno
380380
import fcntl
381381
import pickle
382382

@@ -785,7 +785,11 @@ def communicate(self, input=None):
785785
stderr = None
786786
if self.stdin:
787787
if input:
788-
self.stdin.write(input)
788+
try:
789+
self.stdin.write(input)
790+
except IOError as e:
791+
if e.errno != errno.EPIPE and e.errno != errno.EINVAL:
792+
raise
789793
self.stdin.close()
790794
elif self.stdout:
791795
stdout = self.stdout.read()
@@ -1019,7 +1023,11 @@ def _communicate(self, input):
10191023

10201024
if self.stdin:
10211025
if input is not None:
1022-
self.stdin.write(input)
1026+
try:
1027+
self.stdin.write(input)
1028+
except IOError as e:
1029+
if e.errno != errno.EPIPE:
1030+
raise
10231031
self.stdin.close()
10241032

10251033
if self.stdout:
@@ -1455,9 +1463,16 @@ def close_unregister_and_remove(fd):
14551463
for fd, mode in ready:
14561464
if mode & select.POLLOUT:
14571465
chunk = input[input_offset : input_offset + _PIPE_BUF]
1458-
input_offset += os.write(fd, chunk)
1459-
if input_offset >= len(input):
1460-
close_unregister_and_remove(fd)
1466+
try:
1467+
input_offset += os.write(fd, chunk)
1468+
except OSError as e:
1469+
if e.errno == errno.EPIPE:
1470+
close_unregister_and_remove(fd)
1471+
else:
1472+
raise
1473+
else:
1474+
if input_offset >= len(input):
1475+
close_unregister_and_remove(fd)
14611476
elif mode & select_POLLIN_POLLPRI:
14621477
data = os.read(fd, 4096)
14631478
if not data:
@@ -1499,11 +1514,19 @@ def _communicate_with_select(self, input):
14991514

15001515
if self.stdin in wlist:
15011516
chunk = input[input_offset : input_offset + _PIPE_BUF]
1502-
bytes_written = os.write(self.stdin.fileno(), chunk)
1503-
input_offset += bytes_written
1504-
if input_offset >= len(input):
1505-
self.stdin.close()
1506-
write_set.remove(self.stdin)
1517+
try:
1518+
bytes_written = os.write(self.stdin.fileno(), chunk)
1519+
except OSError as e:
1520+
if e.errno == errno.EPIPE:
1521+
self.stdin.close()
1522+
write_set.remove(self.stdin)
1523+
else:
1524+
raise
1525+
else:
1526+
input_offset += bytes_written
1527+
if input_offset >= len(input):
1528+
self.stdin.close()
1529+
write_set.remove(self.stdin)
15071530

15081531
if self.stdout in rlist:
15091532
data = os.read(self.stdout.fileno(), 1024)

Lib/test/test_subprocess.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,25 @@ def test_handles_closed_on_exception(self):
626626
self.assertFalse(os.path.exists(ofname))
627627
self.assertFalse(os.path.exists(efname))
628628

629+
def test_communicate_epipe(self):
630+
# Issue 10963: communicate() should hide EPIPE
631+
p = subprocess.Popen([sys.executable, "-c", 'pass'],
632+
stdin=subprocess.PIPE,
633+
stdout=subprocess.PIPE,
634+
stderr=subprocess.PIPE)
635+
self.addCleanup(p.stdout.close)
636+
self.addCleanup(p.stderr.close)
637+
self.addCleanup(p.stdin.close)
638+
p.communicate(b"x" * 2**20)
639+
640+
def test_communicate_epipe_only_stdin(self):
641+
# Issue 10963: communicate() should hide EPIPE
642+
p = subprocess.Popen([sys.executable, "-c", 'pass'],
643+
stdin=subprocess.PIPE)
644+
self.addCleanup(p.stdin.close)
645+
time.sleep(2)
646+
p.communicate(b"x" * 2**20)
647+
629648

630649
# context manager
631650
class _SuppressCoreFiles(object):

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ Core and Builtins
4949
Library
5050
-------
5151

52+
- Issue #10963: Ensure that subprocess.communicate() never raises EPIPE.
53+
5254
- Issue #11746: Fix SSLContext.load_cert_chain() to accept elliptic curve
5355
private keys.
5456

Objects/typeslots.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Generated by typeslots.py $Revision: 87806 $ */
1+
/* Generated by typeslots.py $Revision$ */
22
0,
33
0,
44
offsetof(PyHeapTypeObject, as_mapping.mp_ass_subscript),

0 commit comments

Comments
 (0)