summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2016-03-25 00:33:12 +0100
committerVictor Stinner <victor.stinner@gmail.com>2016-03-25 00:33:12 +0100
commit4bce73e77a3f79f90bc407fc952569d46cb4fd2d (patch)
tree350434737136db56323480ffe570b8305d83af71
parentec5f2b9f34d7d9e3288823ba9f3054ab28910010 (diff)
parent7dedf6e34eaa639887effd523ce9f620207b25bd (diff)
downloadcpython-4bce73e77a3f79f90bc407fc952569d46cb4fd2d.tar.gz
Merge 3.5
Issue #21925: warnings.formatwarning() now catches exceptions when calling linecache.getline() and tracemalloc.get_object_traceback() to be able to log ResourceWarning emitted late during the Python shutdown process.
-rw-r--r--Lib/test/test_warnings/__init__.py32
-rw-r--r--Lib/warnings.py31
-rw-r--r--Misc/NEWS5
3 files changed, 57 insertions, 11 deletions
diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py
index e6f47cda4c..9f1cd7574f 100644
--- a/Lib/test/test_warnings/__init__.py
+++ b/Lib/test/test_warnings/__init__.py
@@ -536,6 +536,14 @@ class WCmdLineTests(BaseTest):
self.module._setoption('error::Warning::0')
self.assertRaises(UserWarning, self.module.warn, 'convert to error')
+
+class CWCmdLineTests(WCmdLineTests, unittest.TestCase):
+ module = c_warnings
+
+
+class PyWCmdLineTests(WCmdLineTests, unittest.TestCase):
+ module = py_warnings
+
def test_improper_option(self):
# Same as above, but check that the message is printed out when
# the interpreter is executed. This also checks that options are
@@ -552,12 +560,6 @@ class WCmdLineTests(BaseTest):
self.assertFalse(out.strip())
self.assertNotIn(b'RuntimeWarning', err)
-class CWCmdLineTests(WCmdLineTests, unittest.TestCase):
- module = c_warnings
-
-class PyWCmdLineTests(WCmdLineTests, unittest.TestCase):
- module = py_warnings
-
class _WarningsTests(BaseTest, unittest.TestCase):
@@ -976,6 +978,7 @@ class BootstrapTest(unittest.TestCase):
# Use -W to load warnings module at startup
assert_python_ok('-c', 'pass', '-W', 'always', PYTHONPATH=cwd)
+
class FinalizationTest(unittest.TestCase):
def test_finalization(self):
# Issue #19421: warnings.warn() should not crash
@@ -995,6 +998,23 @@ a=A()
# of the script
self.assertEqual(err, b'__main__:7: UserWarning: test')
+ def test_late_resource_warning(self):
+ # Issue #21925: Emitting a ResourceWarning late during the Python
+ # shutdown must be logged.
+
+ expected = b"sys:1: ResourceWarning: unclosed file "
+
+ # don't import the warnings module
+ # (_warnings will try to import it)
+ code = "f = open(%a)" % __file__
+ rc, out, err = assert_python_ok("-c", code)
+ self.assertTrue(err.startswith(expected), ascii(err))
+
+ # import the warnings module
+ code = "import warnings; f = open(%a)" % __file__
+ rc, out, err = assert_python_ok("-c", code)
+ self.assertTrue(err.startswith(expected), ascii(err))
+
def setUpModule():
py_warnings.onceregistry.clear()
diff --git a/Lib/warnings.py b/Lib/warnings.py
index d4f591ee71..1ece5149f4 100644
--- a/Lib/warnings.py
+++ b/Lib/warnings.py
@@ -33,26 +33,47 @@ def _showwarnmsg_impl(msg):
pass
def _formatwarnmsg_impl(msg):
- import linecache
s = ("%s:%s: %s: %s\n"
% (msg.filename, msg.lineno, msg.category.__name__,
msg.message))
+
if msg.line is None:
- line = linecache.getline(msg.filename, msg.lineno)
+ try:
+ import linecache
+ line = linecache.getline(msg.filename, msg.lineno)
+ except Exception:
+ # When a warning is logged during Python shutdown, linecache
+ # and the improt machinery don't work anymore
+ line = None
+ linecache = None
else:
line = msg.line
if line:
line = line.strip()
s += " %s\n" % line
+
if msg.source is not None:
- import tracemalloc
- tb = tracemalloc.get_object_traceback(msg.source)
+ try:
+ import tracemalloc
+ tb = tracemalloc.get_object_traceback(msg.source)
+ except Exception:
+ # When a warning is logged during Python shutdown, tracemalloc
+ # and the import machinery don't work anymore
+ tb = None
+
if tb is not None:
s += 'Object allocated at (most recent call first):\n'
for frame in tb:
s += (' File "%s", lineno %s\n'
% (frame.filename, frame.lineno))
- line = linecache.getline(frame.filename, frame.lineno)
+
+ try:
+ if linecache is not None:
+ line = linecache.getline(frame.filename, frame.lineno)
+ else:
+ line = None
+ except Exception:
+ line = None
if line:
line = line.strip()
s += ' %s\n' % line
diff --git a/Misc/NEWS b/Misc/NEWS
index 70ff3de8eb..f483735619 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -232,6 +232,11 @@ Core and Builtins
Library
-------
+- Issue #21925: :func:`warnings.formatwarning` now catches exceptions when
+ calling :func;`linecache.getline` and
+ :func:`tracemalloc.get_object_traceback` to be able to log
+ :exc:`ResourceWarning` emitted late during the Python shutdown process.
+
- Issue #23848: On Windows, faulthandler.enable() now also installs an
exception handler to dump the traceback of all Python threads on any Windows
exception, not only on UNIX signals (SIGSEGV, SIGFPE, SIGABRT).