diff --git a/Include/frameobject.h b/Include/frameobject.h --- a/Include/frameobject.h +++ b/Include/frameobject.h @@ -41,10 +41,9 @@ int f_lasti; /* Last instruction if called */ /* Call PyFrame_GetLineNumber() instead of reading this field - directly. As of 2.3 f_lineno is only valid when tracing is - active (i.e. when f_trace is set). At other times we use - PyCode_Addr2Line to calculate the line from the current - bytecode index. */ + directly. As of 2.3 f_lineno is valid when tracing is active. At + other times we use PyCode_Addr2Line to calculate the line from the + current bytecode index. */ int f_lineno; /* Current line number */ int f_iblock; /* index in f_blockstack */ char f_executing; /* whether the frame is still executing */ diff --git a/Objects/frameobject.c b/Objects/frameobject.c --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -30,7 +30,7 @@ int PyFrame_GetLineNumber(PyFrameObject *f) { - if (f->f_trace) + if (f->f_lineno != -1) return f->f_lineno; else return PyCode_Addr2Line(f->f_code, f->f_lasti); @@ -351,9 +351,6 @@ { PyObject* old_value; - /* We rely on f_lineno being accurate when f_trace is set. */ - f->f_lineno = PyFrame_GetLineNumber(f); - old_value = f->f_trace; Py_XINCREF(v); f->f_trace = v; @@ -732,7 +729,7 @@ } f->f_lasti = -1; - f->f_lineno = code->co_firstlineno; + f->f_lineno = -1; f->f_iblock = 0; f->f_executing = 0; f->f_gen = NULL; diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3553,6 +3553,7 @@ tstate, f, PyTrace_RETURN, NULL); } + f->f_lineno = -1; } if (tstate->c_profilefunc) { if (why == WHY_EXCEPTION) @@ -4384,8 +4385,10 @@ void PyEval_SetTrace(Py_tracefunc func, PyObject *arg) { + PyFrameObject *f; PyThreadState *tstate = PyThreadState_GET(); PyObject *temp = tstate->c_traceobj; + _Py_TracingPossible += (func != NULL) - (tstate->c_tracefunc != NULL); Py_XINCREF(arg); tstate->c_tracefunc = NULL; @@ -4398,6 +4401,12 @@ /* Flag that tracing or profiling is turned on */ tstate->use_tracing = ((func != NULL) || (tstate->c_profilefunc != NULL)); + + /* When tracing is set, for all the frames on the stack we rely on + * f_lineno being valid for the case where the next trace event would be + * "return" (see last paragraph of Objects/lnotab_notes.txt). */ + for (f = tstate->frame; f != NULL; f = f->f_back) + f->f_lineno = func ? PyCode_Addr2Line(f->f_code, f->f_lasti) : -1; } void