summaryrefslogtreecommitdiffstats
path: root/Modules/pyexpat.c
diff options
context:
space:
mode:
authorJeremy Hylton <jeremy@alum.mit.edu>2003-06-27 16:13:17 (GMT)
committerJeremy Hylton <jeremy@alum.mit.edu>2003-06-27 16:13:17 (GMT)
commit9263f5797c41dd3c781913ee827992c3686ac8a3 (patch)
treeb6f82a1e1477fc19ffb81d3ac260088364a0fa1b /Modules/pyexpat.c
parent8f6c7c5d5fc43e4a98eef2c1c584d52127a2ed59 (diff)
downloadcpython-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/pyexpat.c')
-rw-r--r--Modules/pyexpat.c63
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);