diff options
author | Jeremy Hylton <jeremy@alum.mit.edu> | 2003-06-27 16:13:17 (GMT) |
---|---|---|
committer | Jeremy Hylton <jeremy@alum.mit.edu> | 2003-06-27 16:13:17 (GMT) |
commit | 9263f5797c41dd3c781913ee827992c3686ac8a3 (patch) | |
tree | b6f82a1e1477fc19ffb81d3ac260088364a0fa1b /Modules | |
parent | 8f6c7c5d5fc43e4a98eef2c1c584d52127a2ed59 (diff) | |
download | cpython-9263f5797c41dd3c781913ee827992c3686ac8a3.zip cpython-9263f5797c41dd3c781913ee827992c3686ac8a3.tar.gz cpython-9263f5797c41dd3c781913ee827992c3686ac8a3.tar.bz2 |
Fix several bugs in handling of exceptions with trace function enabled.
If the callback raised an exception but did not set curexc_traceback,
the trace function was called with PyTrace_RETURN. That is, the trace
function was called with an exception set. The main loop detected the
exception when the trace function returned; it complained and disabled
tracing.
Fix the logic error so that PyTrace_RETURN only occurs if the callback
returned normally.
The trace function must be called for exceptions, too. So we had
to add new functionality to call with PyTrace_EXCEPTION. (Leads to a
rather ugly ifdef / else block that contains only a '}'.)
Reverse the logic and name of NOFIX_TRACE to FIX_TRACE.
Joint work with Fred.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/pyexpat.c | 63 |
1 files changed, 48 insertions, 15 deletions
diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index 0f6608a..5a8423e 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -24,7 +24,8 @@ #if (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 2) /* In Python 2.0 and 2.1, disabling Unicode was not possible. */ #define Py_USING_UNICODE -#define NOFIX_TRACE +#else +#define FIX_TRACE #endif enum HandlerTypes { @@ -293,7 +294,7 @@ getcode(enum HandlerTypes slot, char* func_name, int lineno) return NULL; } -#ifndef NOFIX_TRACE +#ifdef FIX_TRACE static int trace_frame(PyThreadState *tstate, PyFrameObject *f, int code, PyObject *val) { @@ -320,6 +321,37 @@ trace_frame(PyThreadState *tstate, PyFrameObject *f, int code, PyObject *val) } return result; } + +static int +trace_frame_exc(PyThreadState *tstate, PyFrameObject *f) +{ + PyObject *type, *value, *traceback, *arg; + int err; + + if (tstate->c_tracefunc == NULL) + return 0; + + PyErr_Fetch(&type, &value, &traceback); + if (value == NULL) { + value = Py_None; + Py_INCREF(value); + } + arg = Py_BuildValue("(OOO)", type, value, traceback); + if (arg == NULL) { + PyErr_Restore(type, value, traceback); + return 0; + } + err = trace_frame(tstate, f, PyTrace_EXCEPTION, arg); + Py_DECREF(arg); + if (err == 0) + PyErr_Restore(type, value, traceback); + else { + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(traceback); + } + return err; +} #endif static PyObject* @@ -332,31 +364,32 @@ call_with_frame(PyCodeObject *c, PyObject* func, PyObject* args) if (c == NULL) return NULL; - f = PyFrame_New( - tstate, /*back*/ - c, /*code*/ - PyEval_GetGlobals(), /*globals*/ - NULL /*locals*/ - ); + f = PyFrame_New(tstate, c, PyEval_GetGlobals(), NULL); if (f == NULL) return NULL; tstate->frame = f; -#ifndef NOFIX_TRACE - if (trace_frame(tstate, f, PyTrace_CALL, Py_None)) { - Py_DECREF(f); +#ifdef FIX_TRACE + if (trace_frame(tstate, f, PyTrace_CALL, Py_None) < 0) { return NULL; } #endif res = PyEval_CallObject(func, args); - if (res == NULL && tstate->curexc_traceback == NULL) - PyTraceBack_Here(f); -#ifndef NOFIX_TRACE + if (res == NULL) { + if (tstate->curexc_traceback == NULL) + PyTraceBack_Here(f); +#ifdef FIX_TRACE + if (trace_frame_exc(tstate, f) < 0) { + return NULL; + } + } else { - if (trace_frame(tstate, f, PyTrace_RETURN, res)) { + if (trace_frame(tstate, f, PyTrace_RETURN, res) < 0) { Py_XDECREF(res); res = NULL; } } +#else + } #endif tstate->frame = f->f_back; Py_DECREF(f); |