From: Brett Cannon Date: Mon, 29 Sep 2008 03:57:24 +0000 (+0000) Subject: Backport of r66677: _lsprof crasher when a bad external timer is used during X-Git-Tag: v2.5.3c1~34 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=70f1192dfcd2fea86dde9490b57d6fef919ceba1;p=python Backport of r66677: _lsprof crasher when a bad external timer is used during garbage collection of a Profiler object. --- diff --git a/Lib/test/test_cProfile.py b/Lib/test/test_cProfile.py index 07b2a9b54e..f41f404894 100644 --- a/Lib/test/test_cProfile.py +++ b/Lib/test/test_cProfile.py @@ -1,6 +1,5 @@ """Test suite for the cProfile module.""" - -import cProfile, pstats, sys +import cProfile, pstats, sys, test.test_support # In order to have reproducible time, we simulate a timer in the global # variable 'ticks', which represents simulated time in milliseconds. @@ -23,6 +22,7 @@ def test_main(): st.strip_dirs().sort_stats('stdname').print_stats() st.print_callees() st.print_callers() + test_bad_counter_during_dealloc() def timer(): return ticks @@ -119,5 +119,20 @@ class C: ticks += 1 raise AttributeError +# Issue 3895. +def test_bad_counter_during_dealloc(): + import _lsprof + # Must use a file as StringIO doesn't trigger the bug. + sys.stderr = open(test.test_support.TESTFN, 'w') + try: + obj = _lsprof.Profiler(lambda: int) + obj.enable() + obj = _lsprof.Profiler(1) + obj.disable() + finally: + sys.stderr = sys.__stderr__ + test.test_support.unlink(test.test_support.TESTFN) + + if __name__ == "__main__": test_main() diff --git a/Misc/NEWS b/Misc/NEWS index 9ca2febe31..a6ad102e36 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -92,6 +92,9 @@ Core and builtins Library ------- +- Issue #3895: _lsprof could be crashed with an external timer that did not + return a float when a Profiler object is garbage collected. + - Issues #3968 and #3969: two minor turtle problems. - Issue #3547: Fixed ctypes structures bitfields of varying integer diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index 7eb9682323..630b043a8d 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -150,7 +150,16 @@ static PY_LONG_LONG CallExternalTimer(ProfilerObject *pObj) } Py_DECREF(o); if (PyErr_Occurred()) { - PyErr_WriteUnraisable((PyObject *) pObj); + PyObject *context = (PyObject *)pObj; + /* May have been called by profiler_dealloc(). */ + if (context->ob_refcnt < 1) { + context = PyString_FromString("profiler calling an " + "external timer"); + if (context == NULL) { + return 0; + } + } + PyErr_WriteUnraisable(context); return 0; } return result;