Commit 70f1192d authored by Brett Cannon's avatar Brett Cannon

Backport of r66677: _lsprof crasher when a bad external timer is used during

garbage collection of a Profiler object.
parent b50f9926
"""Test suite for the cProfile module.""" """Test suite for the cProfile module."""
import cProfile, pstats, sys, test.test_support
import cProfile, pstats, sys
# In order to have reproducible time, we simulate a timer in the global # In order to have reproducible time, we simulate a timer in the global
# variable 'ticks', which represents simulated time in milliseconds. # variable 'ticks', which represents simulated time in milliseconds.
...@@ -23,6 +22,7 @@ def test_main(): ...@@ -23,6 +22,7 @@ def test_main():
st.strip_dirs().sort_stats('stdname').print_stats() st.strip_dirs().sort_stats('stdname').print_stats()
st.print_callees() st.print_callees()
st.print_callers() st.print_callers()
test_bad_counter_during_dealloc()
def timer(): def timer():
return ticks return ticks
...@@ -119,5 +119,20 @@ class C: ...@@ -119,5 +119,20 @@ class C:
ticks += 1 ticks += 1
raise AttributeError 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__": if __name__ == "__main__":
test_main() test_main()
...@@ -92,6 +92,9 @@ Core and builtins ...@@ -92,6 +92,9 @@ Core and builtins
Library 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. - Issues #3968 and #3969: two minor turtle problems.
- Issue #3547: Fixed ctypes structures bitfields of varying integer - Issue #3547: Fixed ctypes structures bitfields of varying integer
......
...@@ -150,7 +150,16 @@ static PY_LONG_LONG CallExternalTimer(ProfilerObject *pObj) ...@@ -150,7 +150,16 @@ static PY_LONG_LONG CallExternalTimer(ProfilerObject *pObj)
} }
Py_DECREF(o); Py_DECREF(o);
if (PyErr_Occurred()) { 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 0;
} }
return result; return result;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment