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:
parent
d1de6eacf2
commit
4ec5d5699d
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue