Armin Rigo avatar Armin Rigo committed 90bb711

(backport) tracing of C functions: don't call the trace func
with an exception currently set!

Comments (0)

Files changed (1)

 static int call_trace(Py_tracefunc, PyObject *, PyFrameObject *,
 		      int, PyObject *);
 static void call_trace_protected(Py_tracefunc, PyObject *,
-				 PyFrameObject *, int);
+				 PyFrameObject *, int, PyObject *);
 static void call_exc_trace(Py_tracefunc, PyObject *, PyFrameObject *);
 static int maybe_call_line_trace(Py_tracefunc, PyObject *,
 				  PyFrameObject *, int *, int *, int *);
 			else if (why == WHY_EXCEPTION) {
 				call_trace_protected(tstate->c_tracefunc,
 						     tstate->c_traceobj, f,
-						     PyTrace_RETURN);
+						     PyTrace_RETURN, NULL);
 			}
 		}
 		if (tstate->c_profilefunc) {
 			if (why == WHY_EXCEPTION)
 				call_trace_protected(tstate->c_profilefunc,
 						     tstate->c_profileobj, f,
-						     PyTrace_RETURN);
+						     PyTrace_RETURN, NULL);
 			else if (call_trace(tstate->c_profilefunc,
 					    tstate->c_profileobj, f,
 					    PyTrace_RETURN, retval)) {
 
 static void
 call_trace_protected(Py_tracefunc func, PyObject *obj, PyFrameObject *frame,
-		     int what)
+		     int what, PyObject *arg)
 {
 	PyObject *type, *value, *traceback;
 	int err;
 	PyErr_Fetch(&type, &value, &traceback);
-	err = call_trace(func, obj, frame, what, NULL);
+	err = call_trace(func, obj, frame, what, arg);
 	if (err == 0)
 		PyErr_Restore(type, value, traceback);
 	else {
 			     nargs);
 }
 
-#define C_TRACE(call) \
+#define C_TRACE(x, call) \
 if (tstate->use_tracing && tstate->c_profilefunc) { \
 	if (call_trace(tstate->c_profilefunc, \
 		tstate->c_profileobj, \
 		tstate->frame, PyTrace_C_CALL, \
-		func)) \
-		{ return NULL; } \
-	call; \
-	if (tstate->c_profilefunc != NULL) { \
-		if (x == NULL) { \
-			if (call_trace (tstate->c_profilefunc, \
-				tstate->c_profileobj, \
-				tstate->frame, PyTrace_C_EXCEPTION, \
-				func)) \
-				{ return NULL; } \
-		} else { \
-			if (call_trace(tstate->c_profilefunc, \
-				tstate->c_profileobj, \
-				tstate->frame, PyTrace_C_RETURN, \
-				func)) \
-				{ return NULL; } \
+		func)) { \
+		x = NULL; \
+	} \
+	else { \
+		x = call; \
+		if (tstate->c_profilefunc != NULL) { \
+			if (x == NULL) { \
+				call_trace_protected(tstate->c_profilefunc, \
+					tstate->c_profileobj, \
+					tstate->frame, PyTrace_C_EXCEPTION, \
+					func); \
+				/* XXX should pass (type, value, tb) */ \
+			} else { \
+				if (call_trace(tstate->c_profilefunc, \
+					tstate->c_profileobj, \
+					tstate->frame, PyTrace_C_RETURN, \
+					func)) { \
+					Py_DECREF(x); \
+					x = NULL; \
+				} \
+			} \
 		} \
 	} \
 } else { \
-	call; \
+	x = call; \
 	}
 
 static PyObject *
 			PyCFunction meth = PyCFunction_GET_FUNCTION(func);
 			PyObject *self = PyCFunction_GET_SELF(func);
 			if (flags & METH_NOARGS && na == 0) {
-				C_TRACE(x=(*meth)(self,NULL));
+				C_TRACE(x, (*meth)(self,NULL));
 			}
 			else if (flags & METH_O && na == 1) {
 				PyObject *arg = EXT_POP(*pp_stack);
-				C_TRACE(x=(*meth)(self,arg));
+				C_TRACE(x, (*meth)(self,arg));
 				Py_DECREF(arg);
 			}
 			else {
 			PyObject *callargs;
 			callargs = load_args(pp_stack, na);
 			rdtscll(*pintr0);
-			C_TRACE(x=PyCFunction_Call(func,callargs,NULL));
+			C_TRACE(x, PyCFunction_Call(func,callargs,NULL));
 			rdtscll(*pintr1);
 			Py_XDECREF(callargs);
 		}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.