]> granicus.if.org Git - python/commitdiff
This is Richie Hindle's patch:
authorMichael W. Hudson <mwh@python.net>
Fri, 8 Nov 2002 13:08:46 +0000 (13:08 +0000)
committerMichael W. Hudson <mwh@python.net>
Fri, 8 Nov 2002 13:08:46 +0000 (13:08 +0000)
[ 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.

Lib/test/test_trace.py
Python/ceval.c

index 91112e8b2113eee9dc876e0910c40f48996de262..d5fb0e504d86c31fea63e1d3264943058494c52e 100644 (file)
@@ -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)
index 1c95cb9cfbae04123bd1a4280ce09bd31187cb09..e654efd462c05d3961d056c323d377b6a9858aed 100644 (file)
@@ -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