Skip to content

Commit 9517c3a

Browse files
committed
Suppress IOError when closing the temporary file used for capturing streams in Python 2.7.
Fix pytest-dev#2370
1 parent 2612d96 commit 9517c3a

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

_pytest/capture.py

+13-2
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ def done(self):
476476
os.dup2(targetfd_save, self.targetfd)
477477
os.close(targetfd_save)
478478
self.syscapture.done()
479-
self.tmpfile.close()
479+
_attempt_to_close_capture_file(self.tmpfile)
480480

481481
def suspend(self):
482482
self.syscapture.suspend()
@@ -530,7 +530,7 @@ def snap(self):
530530
def done(self):
531531
setattr(sys, self.name, self._old)
532532
del self._old
533-
self.tmpfile.close()
533+
_attempt_to_close_capture_file(self.tmpfile)
534534

535535
def suspend(self):
536536
setattr(sys, self.name, self._old)
@@ -681,3 +681,14 @@ def _reopen_stdio(f, mode):
681681
sys.__stdin__ = sys.stdin = _reopen_stdio(sys.stdin, 'rb')
682682
sys.__stdout__ = sys.stdout = _reopen_stdio(sys.stdout, 'wb')
683683
sys.__stderr__ = sys.stderr = _reopen_stdio(sys.stderr, 'wb')
684+
685+
686+
def _attempt_to_close_capture_file(f):
687+
"""Suppress IOError when closing the temporary file used for capturing streams in py27 (#2370)"""
688+
if six.PY2:
689+
try:
690+
f.close()
691+
except IOError:
692+
pass
693+
else:
694+
f.close()

changelog/2370.bugfix.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Suppress ``IOError`` when closing the temporary file used for capturing streams in Python 2.7.

testing/test_capture.py

+24
Original file line numberDiff line numberDiff line change
@@ -1265,6 +1265,30 @@ def test_capattr():
12651265
reprec.assertoutcome(passed=1)
12661266

12671267

1268+
def test_crash_on_closing_tmpfile_py27(testdir):
1269+
testdir.makepyfile('''
1270+
from __future__ import print_function
1271+
import time
1272+
import threading
1273+
import sys
1274+
1275+
def spam():
1276+
f = sys.stderr
1277+
while True:
1278+
print('.', end='', file=f)
1279+
1280+
def test_silly():
1281+
t = threading.Thread(target=spam)
1282+
t.daemon = True
1283+
t.start()
1284+
time.sleep(0.5)
1285+
1286+
''')
1287+
result = testdir.runpytest_subprocess()
1288+
assert result.ret == 0
1289+
assert 'IOError' not in result.stdout.str()
1290+
1291+
12681292
def test_pickling_and_unpickling_encoded_file():
12691293
# See https://bitbucket.org/pytest-dev/pytest/pull-request/194
12701294
# pickle.loads() raises infinite recursion if

0 commit comments

Comments
 (0)