]> granicus.if.org Git - python/commitdiff
Fix bug in profiler modifications detected only in debug builds.
authorFred Drake <fdrake@acm.org>
Thu, 4 Oct 2001 19:26:43 +0000 (19:26 +0000)
committerFred Drake <fdrake@acm.org>
Thu, 4 Oct 2001 19:26:43 +0000 (19:26 +0000)
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.

Python/ceval.c

index 99822e8f7616942e868f59447f65b7a187a8020f..bccd90d76e475ff2898530909b4fef40896126b3 100644 (file)
@@ -48,6 +48,8 @@ static int prtrace(PyObject *, char *);
 #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 @@ eval_frame(PyFrameObject *f)
                        }
                }
                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 @@ call_exc_trace(Py_tracefunc func, PyObject *self, PyFrameObject *f)
        }
 }
 
+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)