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.
This commit is contained in:
Fred Drake 2001-10-04 19:26:43 +00:00
parent d1de6eacf2
commit 4ec5d5699d
1 changed files with 26 additions and 3 deletions

View File

@ -48,6 +48,8 @@ static int prtrace(PyObject *, char *);
#endif #endif
static int call_trace(Py_tracefunc, PyObject *, PyFrameObject *, static int call_trace(Py_tracefunc, PyObject *, PyFrameObject *,
int, PyObject *); int, PyObject *);
static void call_trace_protected(Py_tracefunc, PyObject *,
PyFrameObject *, int);
static void call_exc_trace(Py_tracefunc, PyObject *, PyFrameObject *); static void call_exc_trace(Py_tracefunc, PyObject *, PyFrameObject *);
static PyObject *loop_subscript(PyObject *, PyObject *); static PyObject *loop_subscript(PyObject *, PyObject *);
static PyObject *apply_slice(PyObject *, PyObject *, PyObject *); static PyObject *apply_slice(PyObject *, PyObject *, PyObject *);
@ -2297,9 +2299,13 @@ eval_frame(PyFrameObject *f)
} }
} }
if (tstate->c_profilefunc) { if (tstate->c_profilefunc) {
if (call_trace(tstate->c_profilefunc, if (why == WHY_EXCEPTION)
tstate->c_profileobj, f, call_trace_protected(tstate->c_profilefunc,
PyTrace_RETURN, retval)) { tstate->c_profileobj, f,
PyTrace_RETURN);
else if (call_trace(tstate->c_profilefunc,
tstate->c_profileobj, f,
PyTrace_RETURN, retval)) {
Py_XDECREF(retval); Py_XDECREF(retval);
retval = NULL; retval = NULL;
why = WHY_EXCEPTION; 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 static int
call_trace(Py_tracefunc func, PyObject *obj, PyFrameObject *frame, call_trace(Py_tracefunc func, PyObject *obj, PyFrameObject *frame,
int what, PyObject *arg) int what, PyObject *arg)