Skip to content

Commit 09f7cc8

Browse files
committed
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.
2 parents f799b2c + 7591538 commit 09f7cc8

File tree

3 files changed

+57
-11
lines changed

3 files changed

+57
-11
lines changed

Lib/test/test_warnings/__init__.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,14 @@ def test_improper_input(self):
536536
self.module._setoption('error::Warning::0')
537537
self.assertRaises(UserWarning, self.module.warn, 'convert to error')
538538

539+
540+
class CWCmdLineTests(WCmdLineTests, unittest.TestCase):
541+
module = c_warnings
542+
543+
544+
class PyWCmdLineTests(WCmdLineTests, unittest.TestCase):
545+
module = py_warnings
546+
539547
def test_improper_option(self):
540548
# Same as above, but check that the message is printed out when
541549
# the interpreter is executed. This also checks that options are
@@ -552,12 +560,6 @@ def test_warnings_bootstrap(self):
552560
self.assertFalse(out.strip())
553561
self.assertNotIn(b'RuntimeWarning', err)
554562

555-
class CWCmdLineTests(WCmdLineTests, unittest.TestCase):
556-
module = c_warnings
557-
558-
class PyWCmdLineTests(WCmdLineTests, unittest.TestCase):
559-
module = py_warnings
560-
561563

562564
class _WarningsTests(BaseTest, unittest.TestCase):
563565

@@ -976,6 +978,7 @@ def test_issue_8766(self):
976978
# Use -W to load warnings module at startup
977979
assert_python_ok('-c', 'pass', '-W', 'always', PYTHONPATH=cwd)
978980

981+
979982
class FinalizationTest(unittest.TestCase):
980983
def test_finalization(self):
981984
# Issue #19421: warnings.warn() should not crash
@@ -995,6 +998,23 @@ def __del__(self):
995998
# of the script
996999
self.assertEqual(err, b'__main__:7: UserWarning: test')
9971000

1001+
def test_late_resource_warning(self):
1002+
# Issue #21925: Emitting a ResourceWarning late during the Python
1003+
# shutdown must be logged.
1004+
1005+
expected = b"sys:1: ResourceWarning: unclosed file "
1006+
1007+
# don't import the warnings module
1008+
# (_warnings will try to import it)
1009+
code = "f = open(%a)" % __file__
1010+
rc, out, err = assert_python_ok("-c", code)
1011+
self.assertTrue(err.startswith(expected), ascii(err))
1012+
1013+
# import the warnings module
1014+
code = "import warnings; f = open(%a)" % __file__
1015+
rc, out, err = assert_python_ok("-c", code)
1016+
self.assertTrue(err.startswith(expected), ascii(err))
1017+
9981018

9991019
def setUpModule():
10001020
py_warnings.onceregistry.clear()

Lib/warnings.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,47 @@ def _showwarnmsg_impl(msg):
3333
pass
3434

3535
def _formatwarnmsg_impl(msg):
36-
import linecache
3736
s = ("%s:%s: %s: %s\n"
3837
% (msg.filename, msg.lineno, msg.category.__name__,
3938
msg.message))
39+
4040
if msg.line is None:
41-
line = linecache.getline(msg.filename, msg.lineno)
41+
try:
42+
import linecache
43+
line = linecache.getline(msg.filename, msg.lineno)
44+
except Exception:
45+
# When a warning is logged during Python shutdown, linecache
46+
# and the improt machinery don't work anymore
47+
line = None
48+
linecache = None
4249
else:
4350
line = msg.line
4451
if line:
4552
line = line.strip()
4653
s += " %s\n" % line
54+
4755
if msg.source is not None:
48-
import tracemalloc
49-
tb = tracemalloc.get_object_traceback(msg.source)
56+
try:
57+
import tracemalloc
58+
tb = tracemalloc.get_object_traceback(msg.source)
59+
except Exception:
60+
# When a warning is logged during Python shutdown, tracemalloc
61+
# and the import machinery don't work anymore
62+
tb = None
63+
5064
if tb is not None:
5165
s += 'Object allocated at (most recent call first):\n'
5266
for frame in tb:
5367
s += (' File "%s", lineno %s\n'
5468
% (frame.filename, frame.lineno))
55-
line = linecache.getline(frame.filename, frame.lineno)
69+
70+
try:
71+
if linecache is not None:
72+
line = linecache.getline(frame.filename, frame.lineno)
73+
else:
74+
line = None
75+
except Exception:
76+
line = None
5677
if line:
5778
line = line.strip()
5879
s += ' %s\n' % line

Misc/NEWS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,11 @@ Core and Builtins
232232
Library
233233
-------
234234

235+
- Issue #21925: :func:`warnings.formatwarning` now catches exceptions when
236+
calling :func;`linecache.getline` and
237+
:func:`tracemalloc.get_object_traceback` to be able to log
238+
:exc:`ResourceWarning` emitted late during the Python shutdown process.
239+
235240
- Issue #23848: On Windows, faulthandler.enable() now also installs an
236241
exception handler to dump the traceback of all Python threads on any Windows
237242
exception, not only on UNIX signals (SIGSEGV, SIGFPE, SIGABRT).

0 commit comments

Comments
 (0)