Issue 7238: frame.f_lineno doesn't get updated after local trace function assigned to it (original) (raw)

As you can see, when a local trace function sets f_lineno, f_lineno doesn't get updated on subsequent lines. Otherwise it works fine. $ python tracer_testcase.py
12 12 12

13 14 15

The reference manual (for python 2.6) states the following: "f_lineno is the current line number of the frame — writing to this from within a trace function jumps to the given line (only for the bottom-most frame). A debugger can implement a Jump command (aka Set Next Statement) by writing to f_lineno.". This is contradictory with the shown results, because apparently it doesn't always represent the current line number.

It's not a bug. What happens is like this:

1, You set trace function using sys.settrace(tracer). 2, When the following func() is called, tracer is called with a "call" event, so the trace function in PyThreadState is set to NULL since "sys.settrace(None)" is execute, but since the return value is a valid local trace function, the frame of called function("func()") has its local trace function. 3, The called function("func()") executes, though its frame has a local trace function, but it will not be executed since PyThreadState->c_tracefunc is NULL. When you get f_lineno from frame, you get the not refreshed f_lineno value but not the dynamically computed lineno, as the f_lineno's getter function said: if(f->f_trace) return f->f_lineno; else return PyCode_Addr2Line(f->f_code, f->f_lasti);

Here because your frame's local trace function is not executed, the f_lineno is not refreshed.

4, When the second time func() calls, there is no global trace function. Each time you get the f_lineno, it uses PyCode_Addr2Line() to get the dynamically computed line number.

I think this situation is so rarely that the doc saying "f_lineno is the current line number of the frame" is correct.