diff Python/ceval.c @ 20257:e3f63a95455f legacy-trunk

Fix bug in profiler modifications detected only in debug builds. The new profiler event stream includes a "return" event even when an exception is being propogated, but the machinery that called the profile hook did not save & restore the exception. In debug mode, the exception was detected during the execution of the profile callback, which did not have the proper internal flags set for the exception. Saving & restoring the exception state solves the problem.
author Fred Drake <fdrake@acm.org>
date Thu, 04 Oct 2001 19:26:43 +0000
parents a4d328d50897
children 2269cb371e05
line wrap: on
line diff
--- a/Python/ceval.c	Thu Oct 04 18:18:37 2001 +0000
+++ b/Python/ceval.c	Thu Oct 04 19:26:43 2001 +0000
@@ -48,6 +48,8 @@
 #endif
 static int call_trace(Py_tracefunc, PyObject *, PyFrameObject *,
 		      int, PyObject *);
+static void call_trace_protected(Py_tracefunc, PyObject *,
+				 PyFrameObject *, int);
 static void call_exc_trace(Py_tracefunc, PyObject *, PyFrameObject *);
 static PyObject *loop_subscript(PyObject *, PyObject *);
 static PyObject *apply_slice(PyObject *, PyObject *, PyObject *);
@@ -2297,9 +2299,13 @@
 			}
 		}
 		if (tstate->c_profilefunc) {
-			if (call_trace(tstate->c_profilefunc,
-				       tstate->c_profileobj, f,
-				       PyTrace_RETURN, retval)) {
+			if (why == WHY_EXCEPTION)
+				call_trace_protected(tstate->c_profilefunc,
+						     tstate->c_profileobj, f,
+						     PyTrace_RETURN);
+			else if (call_trace(tstate->c_profilefunc,
+					    tstate->c_profileobj, f,
+					    PyTrace_RETURN, retval)) {
 				Py_XDECREF(retval);
 				retval = NULL;
 				why = WHY_EXCEPTION;
@@ -2821,6 +2827,23 @@
 	}
 }
 
+static void
+call_trace_protected(Py_tracefunc func, PyObject *obj, PyFrameObject *frame,
+		     int what)
+{
+	PyObject *type, *value, *traceback;
+	int err;
+	PyErr_Fetch(&type, &value, &traceback);
+	err = call_trace(func, obj, frame, what, NULL);
+	if (err == 0)
+		PyErr_Restore(type, value, traceback);
+	else {
+		Py_XDECREF(type);
+		Py_XDECREF(value);
+		Py_XDECREF(traceback);
+	}
+}
+
 static int
 call_trace(Py_tracefunc func, PyObject *obj, PyFrameObject *frame,
 	   int what, PyObject *arg)