]> granicus.if.org Git - python/commitdiff
Backport of r66677: _lsprof crasher when a bad external timer is used during
authorBrett Cannon <bcannon@gmail.com>
Mon, 29 Sep 2008 03:57:24 +0000 (03:57 +0000)
committerBrett Cannon <bcannon@gmail.com>
Mon, 29 Sep 2008 03:57:24 +0000 (03:57 +0000)
garbage collection of a Profiler object.

Lib/test/test_cProfile.py
Misc/NEWS
Modules/_lsprof.c

index 07b2a9b54e39131212531cef2c988e3f7a0dcc0d..f41f404894fbe92c69166323183cf33b8471b40a 100644 (file)
@@ -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()
index 9ca2febe31d9b84b1e3c4ccf666b29387ee1987b..a6ad102e3611766c414434f33bfaeb686bddedc9 100644 (file)
--- 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
index 7eb96823231656fceda4b641a1960b6b3688b1d3..630b043a8ddcea6a8665ea7ec7c6a8660fe12b73 100644 (file)
@@ -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;