Skip to content

Commit

Permalink
Suppress IOError when closing the temporary file used for capturi…
Browse files Browse the repository at this point in the history
…ng streams in Python 2.7.

Fix pytest-dev#2370
  • Loading branch information
nicoddemus committed Mar 13, 2018
1 parent 2612d96 commit 9517c3a
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 9517c3a

Please sign in to comment.