summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorFred Drake <fdrake@acm.org>2001-10-04 19:26:43 (GMT)
committerFred Drake <fdrake@acm.org>2001-10-04 19:26:43 (GMT)
commit4ec5d5699de7a67dac59a59077ee8d0a777df586 (patch)
treecd26b96a9ff7c86373300f29f9098e98f6c2fffd /Python/ceval.c
parentd1de6eacf22caf95aba6d76058267c8f5b6543b8 (diff)
downloadcpython-4ec5d5699de7a67dac59a59077ee8d0a777df586.zip
cpython-4ec5d5699de7a67dac59a59077ee8d0a777df586.tar.gz
cpython-4ec5d5699de7a67dac59a59077ee8d0a777df586.tar.bz2
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.
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 99822e8..bccd90d 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -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)