aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2019-05-23 03:45:09 +0200
committerGitHub <noreply@github.com>2019-05-23 03:45:09 +0200
commitbc2aa816620c5e02ad8e94d8514b7e8f3f551ca1 (patch)
treebf5c847dda365eab94373bc06262d2092dd9077e /Lib/_pyio.py
parentbpo-36721: Add --embed option to python-config (GH-13500) (diff)
downloadcpython-bc2aa816620c5e02ad8e94d8514b7e8f3f551ca1.tar.gz
cpython-bc2aa816620c5e02ad8e94d8514b7e8f3f551ca1.tar.bz2
cpython-bc2aa816620c5e02ad8e94d8514b7e8f3f551ca1.zip
bpo-18748: _pyio.IOBase emits unraisable exception (GH-13512)
In development (-X dev) mode and in a debug build, IOBase finalizer of the _pyio module now logs the exception if the close() method fails. The exception is ignored silently by default in release build. test_io: test_error_through_destructor() now uses support.catch_unraisable_exception() rather than capturing stderr.
Diffstat (limited to 'Lib/_pyio.py')
-rw-r--r--Lib/_pyio.py23
1 files changed, 15 insertions, 8 deletions
diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index af2ce30c278..be5e4266daf 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -33,6 +33,10 @@ DEFAULT_BUFFER_SIZE = 8 * 1024 # bytes
# Rebind for compatibility
BlockingIOError = BlockingIOError
+# Does io.IOBase finalizer log the exception if the close() method fails?
+# The exception is ignored silently by default in release build.
+_IOBASE_EMITS_UNRAISABLE = (hasattr(sys, "gettotalrefcount") or sys.flags.dev_mode)
+
def open(file, mode="r", buffering=-1, encoding=None, errors=None,
newline=None, closefd=True, opener=None):
@@ -378,15 +382,18 @@ class IOBase(metaclass=abc.ABCMeta):
def __del__(self):
"""Destructor. Calls close()."""
- # The try/except block is in case this is called at program
- # exit time, when it's possible that globals have already been
- # deleted, and then the close() call might fail. Since
- # there's nothing we can do about such failures and they annoy
- # the end users, we suppress the traceback.
- try:
+ if _IOBASE_EMITS_UNRAISABLE:
self.close()
- except:
- pass
+ else:
+ # The try/except block is in case this is called at program
+ # exit time, when it's possible that globals have already been
+ # deleted, and then the close() call might fail. Since
+ # there's nothing we can do about such failures and they annoy
+ # the end users, we suppress the traceback.
+ try:
+ self.close()
+ except:
+ pass
### Inquiries ###