summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael W. Hudson <mwh@python.net>2002-11-08 13:08:46 +0000
committerMichael W. Hudson <mwh@python.net>2002-11-08 13:08:46 +0000
commit9dceef1b6b515faf3883f7de9be59fb8ea033c9f (patch)
tree78e3c04e086e9e2b323497c8210ec801b5ea979d
parent01f43f48c2145b6b51955004fa6f166a3b3360ad (diff)
downloadcpython-9dceef1b6b515faf3883f7de9be59fb8ea033c9f.tar.gz
This is Richie Hindle's patch:
[ 631276 ] Exceptions raised by line trace function It conflicted with the patches from Armin I just checked it, so I had to so some bits by hand.
-rw-r--r--Lib/test/test_trace.py37
-rw-r--r--Python/ceval.c23
2 files changed, 47 insertions, 13 deletions
diff --git a/Lib/test/test_trace.py b/Lib/test/test_trace.py
index 91112e8b21..d5fb0e504d 100644
--- a/Lib/test/test_trace.py
+++ b/Lib/test/test_trace.py
@@ -178,23 +178,48 @@ class TraceTestCase(unittest.TestCase):
self.run_test2(settrace_and_raise)
class RaisingTraceFuncTestCase(unittest.TestCase):
- def test_it(self):
- def tr(frame, event, arg):
+ def trace(self, frame, event, arg):
+ """A trace function that raises an exception in response to a
+ specific trace event."""
+ if event == self.raiseOnEvent:
raise ValueError # just something that isn't RuntimeError
- def f():
+ else:
+ return self.trace
+
+ def f(self):
+ """The function to trace; raises an exception if that's the case
+ we're testing, so that the 'exception' trace event fires."""
+ if self.raiseOnEvent == 'exception':
+ x = 0
+ y = 1/x
+ else:
return 1
+
+ def run_test_for_event(self, event):
+ """Tests that an exception raised in response to the given event is
+ handled OK."""
+ self.raiseOnEvent = event
try:
for i in xrange(sys.getrecursionlimit() + 1):
- sys.settrace(tr)
+ sys.settrace(self.trace)
try:
- f()
+ self.f()
except ValueError:
pass
else:
self.fail("exception not thrown!")
except RuntimeError:
self.fail("recursion counter not reset")
-
+
+ # Test the handling of exceptions raised by each kind of trace event.
+ def test_call(self):
+ self.run_test_for_event('call')
+ def test_line(self):
+ self.run_test_for_event('line')
+ def test_return(self):
+ self.run_test_for_event('return')
+ def test_exception(self):
+ self.run_test_for_event('exception')
def test_main():
test_support.run_unittest(TraceTestCase)
diff --git a/Python/ceval.c b/Python/ceval.c
index 1c95cb9cfb..e654efd462 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -51,7 +51,7 @@ static int call_trace(Py_tracefunc, PyObject *, PyFrameObject *,
static void call_trace_protected(Py_tracefunc, PyObject *,
PyFrameObject *, int);
static void call_exc_trace(Py_tracefunc, PyObject *, PyFrameObject *);
-static void maybe_call_line_trace(Py_tracefunc, PyObject *,
+static int maybe_call_line_trace(Py_tracefunc, PyObject *,
PyFrameObject *, int *, int *);
static PyObject *apply_slice(PyObject *, PyObject *, PyObject *);
@@ -726,9 +726,14 @@ eval_frame(PyFrameObject *f)
/* see maybe_call_line_trace
for expository comments */
f->f_stacktop = stack_pointer;
- maybe_call_line_trace(tstate->c_tracefunc,
- tstate->c_traceobj,
- f, &instr_lb, &instr_ub);
+
+ if (maybe_call_line_trace(tstate->c_tracefunc,
+ tstate->c_traceobj,
+ f, &instr_lb, &instr_ub)) {
+ /* trace function raised an exception */
+ why = WHY_EXCEPTION;
+ goto on_error;
+ }
/* Reload possibly changed frame fields */
JUMPTO(f->f_lasti);
stack_pointer = f->f_stacktop;
@@ -2872,7 +2877,7 @@ call_trace(Py_tracefunc func, PyObject *obj, PyFrameObject *frame,
return result;
}
-static void
+static int
maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
PyFrameObject *frame, int *instr_lb, int *instr_ub)
{
@@ -2947,6 +2952,8 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
suggested by f_lasti on this one occasion where it's desirable.
*/
+ int result = 0;
+
if ((frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub)) {
PyCodeObject* co = frame->f_code;
int size, addr, line;
@@ -2980,8 +2987,8 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
if (addr == frame->f_lasti) {
frame->f_lineno = line;
- call_trace(func, obj, frame,
- PyTrace_LINE, Py_None);
+ result = call_trace(func, obj, frame,
+ PyTrace_LINE, Py_None);
}
if (size > 0) {
@@ -2996,6 +3003,8 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
*instr_ub = INT_MAX;
}
}
+
+ return result;
}
void