Skip to content

Commit

Permalink
Merge pull request pytest-dev#3305 from nicoddemus/2370-tmpfile-close…
Browse files Browse the repository at this point in the history
…-py27

Suppress ``IOError`` when closing the temporary file used for capturing streams in Python 2.7
  • Loading branch information
RonnyPfannschmidt authored Mar 14, 2018
2 parents 2612d96 + 9517c3a commit b2b629f
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 2 deletions.
15 changes: 13 additions & 2 deletions _pytest/capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ def done(self):
os.dup2(targetfd_save, self.targetfd)
os.close(targetfd_save)
self.syscapture.done()
self.tmpfile.close()
_attempt_to_close_capture_file(self.tmpfile)

def suspend(self):
self.syscapture.suspend()
Expand Down Expand Up @@ -530,7 +530,7 @@ def snap(self):
def done(self):
setattr(sys, self.name, self._old)
del self._old
self.tmpfile.close()
_attempt_to_close_capture_file(self.tmpfile)

def suspend(self):
setattr(sys, self.name, self._old)
Expand Down Expand Up @@ -681,3 +681,14 @@ def _reopen_stdio(f, mode):
sys.__stdin__ = sys.stdin = _reopen_stdio(sys.stdin, 'rb')
sys.__stdout__ = sys.stdout = _reopen_stdio(sys.stdout, 'wb')
sys.__stderr__ = sys.stderr = _reopen_stdio(sys.stderr, 'wb')


def _attempt_to_close_capture_file(f):
"""Suppress IOError when closing the temporary file used for capturing streams in py27 (#2370)"""
if six.PY2:
try:
f.close()
except IOError:
pass
else:
f.close()
1 change: 1 addition & 0 deletions changelog/2370.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Suppress ``IOError`` when closing the temporary file used for capturing streams in Python 2.7.
24 changes: 24 additions & 0 deletions testing/test_capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -1265,6 +1265,30 @@ def test_capattr():
reprec.assertoutcome(passed=1)


def test_crash_on_closing_tmpfile_py27(testdir):
testdir.makepyfile('''
from __future__ import print_function
import time
import threading
import sys
def spam():
f = sys.stderr
while True:
print('.', end='', file=f)
def test_silly():
t = threading.Thread(target=spam)
t.daemon = True
t.start()
time.sleep(0.5)
''')
result = testdir.runpytest_subprocess()
assert result.ret == 0
assert 'IOError' not in result.stdout.str()


def test_pickling_and_unpickling_encoded_file():
# See https://bitbucket.org/pytest-dev/pytest/pull-request/194
# pickle.loads() raises infinite recursion if
Expand Down

0 comments on commit b2b629f

Please sign in to comment.