private static TraceThread GetOrCreateThread() { TraceThread thread = _threads; if (thread == null) { _threads = thread = new TraceThread(); thread.Frames = new List<TraceBackFrame>(); } return thread; }
private void DispatchTrace(TraceThread thread, Debugging.TraceEventKind kind, object payload, TracebackDelegate traceDispatch, object traceDispatchObject, TraceBackFrame pyFrame) { object args = null; // Prepare the event string traceEvent = String.Empty; switch (kind) { case Debugging.TraceEventKind.FrameEnter: traceEvent = "call"; break; case Debugging.TraceEventKind.TracePoint: traceEvent = "line"; break; case Debugging.TraceEventKind.Exception: traceEvent = "exception"; object pyException = PythonExceptions.ToPython((Exception)payload); object pyType = ((IPythonObject)pyException).PythonType; args = PythonTuple.MakeTuple(pyType, pyException, null); break; case Debugging.TraceEventKind.FrameExit: traceEvent = "return"; args = payload; break; } bool traceDispatchThrew = true; PythonContext.TracePipeline.TraceCallback = null; thread.InTraceback = true; try { TracebackDelegate dlg = traceDispatch(pyFrame, traceEvent, args); traceDispatchThrew = false; pyFrame.Setf_trace(dlg); } finally { thread.InTraceback = false; PythonContext.TracePipeline.TraceCallback = this; if (traceDispatchThrew) { // We're matching CPython's behavior here. If the trace dispatch throws any exceptions // we don't re-enable tracebacks. We need to leave the trace callback in place though // so that we can pop our frames. _globalTraceObject = _globalTraceDispatch = null; _exceptionThrown = true; } } }