The _lsprof module could crash the interpreter if it was given an external
timer that did not return a float and a timer was still running when the
Profiler object was garbage collected.

Fixes issue 3895.
Code review by Benjamin Peterson.
diff --git a/Lib/test/test_cprofile.py b/Lib/test/test_cprofile.py
index 7ed6cec..13c1060 100755
--- a/Lib/test/test_cprofile.py
+++ b/Lib/test/test_cprofile.py
@@ -1,7 +1,7 @@
 """Test suite for the cProfile module."""
 
 import sys
-from test.test_support import run_unittest
+from test.test_support import run_unittest, TESTFN, unlink
 
 # rip off all interesting stuff from test_profile
 import cProfile
@@ -10,6 +10,20 @@
 class CProfileTest(ProfileTest):
     profilerclass = cProfile.Profile
 
+    # Issue 3895.
+    def test_bad_counter_during_dealloc(self):
+        import _lsprof
+        # Must use a file as StringIO doesn't trigger the bug.
+        sys.stderr = open(TESTFN, 'w')
+        try:
+            obj = _lsprof.Profiler(lambda: int)
+            obj.enable()
+            obj = _lsprof.Profiler(1)
+            obj.disable()
+        finally:
+            sys.stderr = sys.__stderr__
+            unlink(TESTFN)
+
 
 def test_main():
     run_unittest(CProfileTest)
diff --git a/Misc/NEWS b/Misc/NEWS
index 97fa2b7..466160f 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -23,6 +23,10 @@
 Library
 -------
 
+- Issue #3895: It was possible to crash the interpreter when an external timer
+  was used with cProfile that returned an object that could not be converted
+  into a float.
+
 - Issue #3950: Made turtle respect scale factors.
 
 - Issue #3547: Fixed ctypes structures bitfields of varying integer
diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c
index 5d18c33..41c477e 100644
--- a/Modules/_lsprof.c
+++ b/Modules/_lsprof.c
@@ -150,7 +150,16 @@
 	}
 	Py_DECREF(o);
 	if (PyErr_Occurred()) {
-		PyErr_WriteUnraisable((PyObject *) pObj);
+		PyObject *context = (PyObject *)pObj;
+		/* May have been called by profiler_dealloc(). */
+		if (Py_REFCNT(context) < 1) {
+			context = PyString_FromString("profiler calling an "
+							"external timer");
+			if (context == NULL) {
+				return 0;
+			}
+		}
+		PyErr_WriteUnraisable(context);
 		return 0;
 	}
 	return result;